[dubbo-admin]dubbo管理工具自行编译及bug解决方案[AuthorizationValve of uri]

前言

在下在做微服务相关内容,要配置一下dubbo的管理工具,偏偏又遇到bug。。。
果然码农是不会一帆风顺的。

参考资料

dubbo-admin管理平台搭建

正式配置

注意点1:
值得注意的是,
文章中引用的是当时旧版本的incubator-dubbo项目,而新版本的是没有dubbo-admin的,如下:
[dubbo-admin]dubbo管理工具自行编译及bug解决方案[AuthorizationValve of uri]_第1张图片

所以,旧版本在这里:
incubator-dubbo 2.5.x

[dubbo-admin]dubbo管理工具自行编译及bug解决方案[AuthorizationValve of uri]_第2张图片

注意点2:
在下用的是idea,下载完以后,导入,然后可以看到:
[dubbo-admin]dubbo管理工具自行编译及bug解决方案[AuthorizationValve of uri]_第3张图片

针对admin模块配置运行规则,如下:
[dubbo-admin]dubbo管理工具自行编译及bug解决方案[AuthorizationValve of uri]_第4张图片

好了,然后编译运行,你会发现:
[dubbo-admin]dubbo管理工具自行编译及bug解决方案[AuthorizationValve of uri]_第5张图片

…无限重复

AuthorizationValve of uri

这玩意,然后搜索文件你会看到:
[dubbo-admin]dubbo管理工具自行编译及bug解决方案[AuthorizationValve of uri]_第6张图片

[dubbo-admin]dubbo管理工具自行编译及bug解决方案[AuthorizationValve of uri]_第7张图片

这就是原因了,不停redirect登录界面。。。
经过调试你会发现:
[dubbo-admin]dubbo管理工具自行编译及bug解决方案[AuthorizationValve of uri]_第8张图片
这个玩意明明已经输出到response要登录了,但还是在本线程内无限循环,
[dubbo-admin]dubbo管理工具自行编译及bug解决方案[AuthorizationValve of uri]_第9张图片
所以要强制跳出循环才行。

…经过本人细心验证及求证,然后将代码改到亲生父母都认不得,最后发现了一个问题。
代码如下:

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.alibaba.dubbo.governance.web.common.interceptor;

import com.alibaba.citrus.service.pipeline.Pipeline;
import com.alibaba.citrus.service.pipeline.PipelineContext;
import com.alibaba.citrus.service.pipeline.support.AbstractValve;
import com.alibaba.dubbo.common.logger.Logger;
import com.alibaba.dubbo.common.logger.LoggerFactory;
import com.alibaba.dubbo.common.utils.StringUtils;
import com.alibaba.dubbo.governance.service.UserService;
import com.alibaba.dubbo.governance.web.util.WebConstants;
import com.alibaba.dubbo.registry.common.domain.User;
import com.alibaba.dubbo.registry.common.util.Coder;

import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class AuthorizationValve extends AbstractValve {

    private static final Logger logger = LoggerFactory.getLogger(AuthorizationValve.class);
    private static final String BASIC_CHALLENGE = "Basic";
    private static final String DIGEST_CHALLENGE = "Digest";
    private static final String CHALLENGE = BASIC_CHALLENGE;
    private static final String REALM = User.REALM;
    private static Pattern PARAMETER_PATTERN = Pattern.compile("(\\w+)=[\"]?([^,\"]+)[\"]?[,]?\\s*");
    @Autowired
    private HttpServletRequest request;
    @Autowired
    private HttpServletResponse response;
    @Autowired
    private UserService userService;
    private String logout = "/logout";
    private String logoutCookie = "logout";

    static Map parseParameters(String query) {
        Matcher matcher = PARAMETER_PATTERN.matcher(query);
        Map map = new HashMap();
        while (matcher.find()) {
            String key = matcher.group(1);
            String value = matcher.group(2);
            map.put(key, value);
        }
        return map;
    }

    static byte[] readToBytes(InputStream in) throws IOException {
        byte[] buf = new byte[in.available()];
        in.read(buf);
        return buf;
    }

    @Override
    protected void init() throws Exception {
    }

    public void invoke(PipelineContext pipelineContext) throws Exception {
        if (logger.isInfoEnabled()) {
            logger.info("AuthorizationValve of uri: " + request.getRequestURI());
        }
//        if(1==1){
//            pipelineContext.invokeNext();
//            return;
//        }
        System.out.println("pipeline 序号:"+pipelineContext.index()+" pipeline状态");
        System.out.println("is finish:"+pipelineContext.isFinished());
        System.out.println("is broken:"+pipelineContext.isBroken());
        System.out.println("game over 标识为:"+pipelineContext.getAttribute("game_over"));
        String uri = request.getRequestURI();
        String contextPath = request.getContextPath();
        if (contextPath != null && contextPath.length() > 0 && !"/".equals(contextPath)) {
            uri = uri.substring(contextPath.length());
        }
        if (uri.equals(logout)) {
            if (!isLogout()) {
                setLogout(true);
                showLoginForm();
            } else {
                setLogout(false);
                response.sendRedirect(contextPath == null || contextPath.length() == 0 ? "/" : contextPath);
            }
            return;
        }
        //FIXME
        if (!uri.startsWith("/status/")) {
            User user = null;
            String authType = null;
            String authorization = request.getHeader("Authorization");
            if (authorization != null && authorization.length() > 0) {
                int i = authorization.indexOf(' ');
                if (i >= 0) {
                    authType = authorization.substring(0, i);
                    String authPrincipal = authorization.substring(i + 1);
                    if (BASIC_CHALLENGE.equalsIgnoreCase(authType)) {
                        user = loginByBase(authPrincipal);
                    } else if (DIGEST_CHALLENGE.equalsIgnoreCase(authType)) {
                        user = loginByDigest(authPrincipal);
                    }
                }
            }
            if (user == null || user.getUsername() == null || user.getUsername().length() == 0) {
                showLoginForm();
//                pipelineContext.breakPipeline(Pipeline.TOP_LABEL);
//                pipelineContext.breakPipeline(1);
                pipelineContext.setAttribute("game_over",true);
                pipelineContext.breakPipeline(1);

                return;

            }
            if (user != null && StringUtils.isNotEmpty(user.getUsername())) {
                request.getSession().setAttribute(WebConstants.CURRENT_USER_KEY, user);
                pipelineContext.invokeNext();
            }
        } else {
            pipelineContext.invokeNext();
        }
    }

    private User getUser(String username) {
        return userService.findUser(username);
    }

    private void showLoginForm() throws IOException {
        if(1==1){
            response.sendRedirect("http://www.baidu.com");
            return;
        }
        if (DIGEST_CHALLENGE.equals(CHALLENGE)) {
            response.setHeader("WWW-Authenticate", CHALLENGE + " realm=\"" + REALM + "\", qop=\"auth\", nonce=\""
                    + UUID.randomUUID().toString().replace("-", "") + "\", opaque=\""
                    + Coder.encodeMd5(REALM) + "\"");
        } else {
            response.setHeader("WWW-Authenticate", CHALLENGE + " realm=\"" + REALM + "\"");
        }
        response.setHeader("Cache-Control", "must-revalidate,no-cache,no-store");
        response.setHeader("Content-Type", "text/html; charset=iso-8859-1");
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
    }

    private User loginByBase(String authorization) {
        authorization = Coder.decodeBase64(authorization);
        int i = authorization.indexOf(':');
        String username = authorization.substring(0, i);
        if (username != null && username.length() > 0) {
            String password = authorization.substring(i + 1);
            if (password != null && password.length() > 0) {
                String passwordDigest = Coder.encodeMd5(username + ":" + REALM + ":" + password);
                User user = getUser(username);
                if (user != null) {
                    String pwd = user.getPassword();
                    if (pwd != null && pwd.length() > 0) {
                        if (passwordDigest.equals(pwd)) {
                            return user;
                        }
                    }
                }
            }
        }
        return null;
    }

    private User loginByDigest(String value) throws IOException {
        Map params = parseParameters(value);
        String username = params.get("username");
        if (username != null && username.length() > 0) {
            String passwordDigest = params.get("response");
            if (passwordDigest != null && passwordDigest.length() > 0) {
                User user = getUser(username);
                if (user != null) {
                    String pwd = user.getPassword();
                    // A valid user, validate password
                    if (pwd != null && pwd.length() > 0) {
                        String uri = params.get("uri");
                        String nonce = params.get("nonce");
                        String nc = params.get("nc");
                        String cnonce = params.get("cnonce");
                        String qop = params.get("qop");
                        String method = request.getMethod();
                        String a1 = pwd;

                        String a2 = "auth-int".equals(qop)
                                ? Coder.encodeMd5(method + ":" + uri + ":" + Coder.encodeMd5(readToBytes(request.getInputStream())))
                                : Coder.encodeMd5(method + ":" + uri);
                        String digest = "auth".equals(qop) || "auth-int".equals(qop)
                                ? Coder.encodeMd5(a1 + ":" + nonce + ":" + nc + ":" + cnonce + ":" + qop + ":" + a2)
                                : Coder.encodeMd5(a1 + ":" + nonce + ":" + a2);
                        if (digest.equals(passwordDigest)) {
                            return user;
                        }
                    }
                }
            }
        }
        return null;
    }

    private boolean isLogout() {
        Cookie[] cookies = request.getCookies();
        if (cookies != null && cookies.length > 0) {
            for (Cookie cookie : cookies) {
                if (cookie != null && logoutCookie.equals(cookie.getName())) {
                    return "true".equals(cookie.getValue());
                }
            }
        }
        return false;
    }

    private void setLogout(boolean logoutValue) {
        response.addCookie(new Cookie(logoutCookie, String.valueOf(logoutValue)));
    }
}

运行结果:

 INFO interceptor.AuthorizationValve -  [DUBBO] AuthorizationValve of uri: /, dubbo version: 2.5.10, current host: 192.168.1.190
pipeline 序号:1 pipeline状态
is finish:false
is broken:false
game over 标识为:null
 INFO interceptor.AuthorizationValve -  [DUBBO] AuthorizationValve of uri: /, dubbo version: 2.5.10, current host: 192.168.1.190
pipeline 序号:1 pipeline状态
is finish:false
is broken:false
game over 标识为:null
 INFO interceptor.AuthorizationValve -  [DUBBO] AuthorizationValve of uri: /, dubbo version: 2.5.10, current host: 192.168.1.190
pipeline 序号:1 pipeline状态
is finish:false
is broken:false
game over 标识为:null

好了,我不卖关子了,结果就是,showLoginForm这方法如果不是用sendRerict阻断了,这pipeline永远都运行在index=1的程度就是变成死循环,于是我们可以得出,showLoginForm这个有问题,是元凶。。
为什么是元凶?额,我没了解过webx的运行机制,说不上来,但可以改,
我们新建一个jsp页面专门用来登录即可,譬如:
login.jsp

<%@ page import="java.util.UUID" %>
<%@ page import="com.alibaba.dubbo.registry.common.util.Coder" %>
<%@ page import="com.alibaba.dubbo.registry.common.domain.User" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
  final String BASIC_CHALLENGE = "Basic";
  final String DIGEST_CHALLENGE = "Digest";
  final String CHALLENGE = BASIC_CHALLENGE;
  final String REALM = User.REALM;
  if (DIGEST_CHALLENGE.equals(CHALLENGE)) {
    response.setHeader("WWW-Authenticate", CHALLENGE + " realm=\"" + REALM + "\", qop=\"auth\", nonce=\""
            + UUID.randomUUID().toString().replace("-", "") + "\", opaque=\""
            + Coder.encodeMd5(REALM) + "\"");
  } else {
    response.setHeader("WWW-Authenticate", CHALLENGE + " realm=\"" + REALM + "\"");
  }
  response.setHeader("Cache-Control", "must-revalidate,no-cache,no-store");
  response.setHeader("Content-Type", "text/html; charset=iso-8859-1");
  response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
%>

然后,代码改为:

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.alibaba.dubbo.governance.web.common.interceptor;

import com.alibaba.citrus.service.pipeline.Pipeline;
import com.alibaba.citrus.service.pipeline.PipelineContext;
import com.alibaba.citrus.service.pipeline.support.AbstractValve;
import com.alibaba.dubbo.common.logger.Logger;
import com.alibaba.dubbo.common.logger.LoggerFactory;
import com.alibaba.dubbo.common.utils.StringUtils;
import com.alibaba.dubbo.governance.service.UserService;
import com.alibaba.dubbo.governance.web.util.WebConstants;
import com.alibaba.dubbo.registry.common.domain.User;
import com.alibaba.dubbo.registry.common.util.Coder;

import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class AuthorizationValve extends AbstractValve {

    private static final Logger logger = LoggerFactory.getLogger(AuthorizationValve.class);
    private static final String BASIC_CHALLENGE = "Basic";
    private static final String DIGEST_CHALLENGE = "Digest";
    private static final String CHALLENGE = BASIC_CHALLENGE;
    private static final String REALM = User.REALM;
    private static Pattern PARAMETER_PATTERN = Pattern.compile("(\\w+)=[\"]?([^,\"]+)[\"]?[,]?\\s*");
    @Autowired
    private HttpServletRequest request;
    @Autowired
    private HttpServletResponse response;
    @Autowired
    private UserService userService;
    private String logout = "/logout";
    private String logoutCookie = "logout";

    static Map parseParameters(String query) {
        Matcher matcher = PARAMETER_PATTERN.matcher(query);
        Map map = new HashMap();
        while (matcher.find()) {
            String key = matcher.group(1);
            String value = matcher.group(2);
            map.put(key, value);
        }
        return map;
    }

    static byte[] readToBytes(InputStream in) throws IOException {
        byte[] buf = new byte[in.available()];
        in.read(buf);
        return buf;
    }

    @Override
    protected void init() throws Exception {
    }

    public void invoke(PipelineContext pipelineContext) throws Exception {
        if (logger.isInfoEnabled()) {
            logger.info("AuthorizationValve of uri: " + request.getRequestURI());
        }
//        if(1==1){
//            pipelineContext.invokeNext();
//            return;
//        }
        System.out.println("pipeline 序号:"+pipelineContext.index()+" pipeline状态");
        System.out.println("is finish:"+pipelineContext.isFinished());
        System.out.println("is broken:"+pipelineContext.isBroken());
        System.out.println("game over 标识为:"+pipelineContext.getAttribute("game_over"));
        String uri = request.getRequestURI();
        String contextPath = request.getContextPath();
        if (contextPath != null && contextPath.length() > 0 && !"/".equals(contextPath)) {
            uri = uri.substring(contextPath.length());
        }
        if (uri.equals(logout)) {
            if (!isLogout()) {
                setLogout(true);
                showLoginForm();
            } else {
                setLogout(false);
                response.sendRedirect(contextPath == null || contextPath.length() == 0 ? "/" : contextPath);
            }
            return;
        }
        //FIXME
        if (!uri.startsWith("/status/")) {
            User user = null;
            String authType = null;
            String authorization = request.getHeader("Authorization");
            if (authorization != null && authorization.length() > 0) {
                int i = authorization.indexOf(' ');
                if (i >= 0) {
                    authType = authorization.substring(0, i);
                    String authPrincipal = authorization.substring(i + 1);
                    if (BASIC_CHALLENGE.equalsIgnoreCase(authType)) {
                        user = loginByBase(authPrincipal);
                    } else if (DIGEST_CHALLENGE.equalsIgnoreCase(authType)) {
                        user = loginByDigest(authPrincipal);
                    }
                }
            }
            if (user == null || user.getUsername() == null || user.getUsername().length() == 0) {
                showLoginForm();
//                pipelineContext.breakPipeline(Pipeline.TOP_LABEL);
//                pipelineContext.breakPipeline(1);
                pipelineContext.setAttribute("game_over",true);
                pipelineContext.breakPipeline(1);

                return;

            }
            if (user != null && StringUtils.isNotEmpty(user.getUsername())) {
                request.getSession().setAttribute(WebConstants.CURRENT_USER_KEY, user);
                pipelineContext.invokeNext();
            }
        } else {
            pipelineContext.invokeNext();
        }
    }

    private User getUser(String username) {
        return userService.findUser(username);
    }

    private void showLoginForm() throws IOException {
        if(1==1){
            response.sendRedirect("/login.jsp");
            return;
        }
        if (DIGEST_CHALLENGE.equals(CHALLENGE)) {
            response.setHeader("WWW-Authenticate", CHALLENGE + " realm=\"" + REALM + "\", qop=\"auth\", nonce=\""
                    + UUID.randomUUID().toString().replace("-", "") + "\", opaque=\""
                    + Coder.encodeMd5(REALM) + "\"");
        } else {
            response.setHeader("WWW-Authenticate", CHALLENGE + " realm=\"" + REALM + "\"");
        }
        response.setHeader("Cache-Control", "must-revalidate,no-cache,no-store");
        response.setHeader("Content-Type", "text/html; charset=iso-8859-1");
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
    }

    private User loginByBase(String authorization) {
        authorization = Coder.decodeBase64(authorization);
        int i = authorization.indexOf(':');
        String username = authorization.substring(0, i);
        if (username != null && username.length() > 0) {
            String password = authorization.substring(i + 1);
            if (password != null && password.length() > 0) {
                String passwordDigest = Coder.encodeMd5(username + ":" + REALM + ":" + password);
                User user = getUser(username);
                if (user != null) {
                    String pwd = user.getPassword();
                    if (pwd != null && pwd.length() > 0) {
                        if (passwordDigest.equals(pwd)) {
                            return user;
                        }
                    }
                }
            }
        }
        return null;
    }

    private User loginByDigest(String value) throws IOException {
        Map params = parseParameters(value);
        String username = params.get("username");
        if (username != null && username.length() > 0) {
            String passwordDigest = params.get("response");
            if (passwordDigest != null && passwordDigest.length() > 0) {
                User user = getUser(username);
                if (user != null) {
                    String pwd = user.getPassword();
                    // A valid user, validate password
                    if (pwd != null && pwd.length() > 0) {
                        String uri = params.get("uri");
                        String nonce = params.get("nonce");
                        String nc = params.get("nc");
                        String cnonce = params.get("cnonce");
                        String qop = params.get("qop");
                        String method = request.getMethod();
                        String a1 = pwd;

                        String a2 = "auth-int".equals(qop)
                                ? Coder.encodeMd5(method + ":" + uri + ":" + Coder.encodeMd5(readToBytes(request.getInputStream())))
                                : Coder.encodeMd5(method + ":" + uri);
                        String digest = "auth".equals(qop) || "auth-int".equals(qop)
                                ? Coder.encodeMd5(a1 + ":" + nonce + ":" + nc + ":" + cnonce + ":" + qop + ":" + a2)
                                : Coder.encodeMd5(a1 + ":" + nonce + ":" + a2);
                        if (digest.equals(passwordDigest)) {
                            return user;
                        }
                    }
                }
            }
        }
        return null;
    }

    private boolean isLogout() {
        Cookie[] cookies = request.getCookies();
        if (cookies != null && cookies.length > 0) {
            for (Cookie cookie : cookies) {
                if (cookie != null && logoutCookie.equals(cookie.getName())) {
                    return "true".equals(cookie.getValue());
                }
            }
        }
        return false;
    }

    private void setLogout(boolean logoutValue) {
        response.addCookie(new Cookie(logoutCookie, String.valueOf(logoutValue)));
    }
}

然后,在web xml中这里:

[dubbo-admin]dubbo管理工具自行编译及bug解决方案[AuthorizationValve of uri]_第10张图片

加上对jsp后缀的忽略:

[dubbo-admin]dubbo管理工具自行编译及bug解决方案[AuthorizationValve of uri]_第11张图片

这是不行的,所以:
我直接不执行这个pipeline了,

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.alibaba.dubbo.governance.web.common.interceptor;

import com.alibaba.citrus.service.pipeline.Pipeline;
import com.alibaba.citrus.service.pipeline.PipelineContext;
import com.alibaba.citrus.service.pipeline.support.AbstractValve;
import com.alibaba.dubbo.common.logger.Logger;
import com.alibaba.dubbo.common.logger.LoggerFactory;
import com.alibaba.dubbo.common.utils.StringUtils;
import com.alibaba.dubbo.governance.service.UserService;
import com.alibaba.dubbo.governance.web.util.WebConstants;
import com.alibaba.dubbo.registry.common.domain.User;
import com.alibaba.dubbo.registry.common.util.Coder;

import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class AuthorizationValve extends AbstractValve {

    private static final Logger logger = LoggerFactory.getLogger(AuthorizationValve.class);
    private static final String BASIC_CHALLENGE = "Basic";
    private static final String DIGEST_CHALLENGE = "Digest";
    private static final String CHALLENGE = BASIC_CHALLENGE;
    private static final String REALM = User.REALM;
    private static Pattern PARAMETER_PATTERN = Pattern.compile("(\\w+)=[\"]?([^,\"]+)[\"]?[,]?\\s*");
    @Autowired
    private HttpServletRequest request;
    @Autowired
    private HttpServletResponse response;
    @Autowired
    private UserService userService;
    private String logout = "/logout";
    private String logoutCookie = "logout";

    static Map parseParameters(String query) {
        Matcher matcher = PARAMETER_PATTERN.matcher(query);
        Map map = new HashMap();
        while (matcher.find()) {
            String key = matcher.group(1);
            String value = matcher.group(2);
            map.put(key, value);
        }
        return map;
    }

    static byte[] readToBytes(InputStream in) throws IOException {
        byte[] buf = new byte[in.available()];
        in.read(buf);
        return buf;
    }

    @Override
    protected void init() throws Exception {
    }

    public void invoke(PipelineContext pipelineContext) throws Exception {
        if (logger.isInfoEnabled()) {
            logger.info("AuthorizationValve of uri: " + request.getRequestURI());
        }
        if(1==1){
            return;
        }
//        if(1==1){
//            pipelineContext.invokeNext();
//            return;
//        }

        System.out.println("pipeline 序号:"+pipelineContext.index()+" pipeline状态");
        System.out.println("is finish:"+pipelineContext.isFinished());
        System.out.println("is broken:"+pipelineContext.isBroken());
        System.out.println("game over 标识为:"+pipelineContext.getAttribute("game_over"));
        String uri = request.getRequestURI();
        String contextPath = request.getContextPath();
        if (contextPath != null && contextPath.length() > 0 && !"/".equals(contextPath)) {
            uri = uri.substring(contextPath.length());
        }
        if (uri.equals(logout)) {
            if (!isLogout()) {
                setLogout(true);
                showLoginForm();
            } else {
                setLogout(false);
                response.sendRedirect(contextPath == null || contextPath.length() == 0 ? "/" : contextPath);
            }
            return;
        }
        //FIXME
        if (!uri.startsWith("/status/")) {
            User user = null;
            String authType = null;
            String authorization = request.getHeader("Authorization");
            if (authorization != null && authorization.length() > 0) {
                int i = authorization.indexOf(' ');
                if (i >= 0) {
                    authType = authorization.substring(0, i);
                    String authPrincipal = authorization.substring(i + 1);
                    if (BASIC_CHALLENGE.equalsIgnoreCase(authType)) {
                        user = loginByBase(authPrincipal);
                    } else if (DIGEST_CHALLENGE.equalsIgnoreCase(authType)) {
                        user = loginByDigest(authPrincipal);
                    }
                }
            }
            if (user == null || user.getUsername() == null || user.getUsername().length() == 0) {
                showLoginForm();
//                pipelineContext.breakPipeline(Pipeline.TOP_LABEL);
//                pipelineContext.breakPipeline(1);
                pipelineContext.setAttribute("game_over",true);
                pipelineContext.breakPipeline(1);

                return;

            }
            if (user != null && StringUtils.isNotEmpty(user.getUsername())) {
                request.getSession().setAttribute(WebConstants.CURRENT_USER_KEY, user);
                pipelineContext.invokeNext();
            }
        } else {
            pipelineContext.invokeNext();
        }
    }

    private User getUser(String username) {
        return userService.findUser(username);
    }

    private void showLoginForm() throws IOException {
        if(1==1){
            response.sendRedirect("/login.jsp");
            return;
        }
        if (DIGEST_CHALLENGE.equals(CHALLENGE)) {
            response.setHeader("WWW-Authenticate", CHALLENGE + " realm=\"" + REALM + "\", qop=\"auth\", nonce=\""
                    + UUID.randomUUID().toString().replace("-", "") + "\", opaque=\""
                    + Coder.encodeMd5(REALM) + "\"");
        } else {
            response.setHeader("WWW-Authenticate", CHALLENGE + " realm=\"" + REALM + "\"");
        }
        response.setHeader("Cache-Control", "must-revalidate,no-cache,no-store");
        response.setHeader("Content-Type", "text/html; charset=iso-8859-1");
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
    }

    private User loginByBase(String authorization) {
        authorization = Coder.decodeBase64(authorization);
        int i = authorization.indexOf(':');
        String username = authorization.substring(0, i);
        if (username != null && username.length() > 0) {
            String password = authorization.substring(i + 1);
            if (password != null && password.length() > 0) {
                String passwordDigest = Coder.encodeMd5(username + ":" + REALM + ":" + password);
                User user = getUser(username);
                if (user != null) {
                    String pwd = user.getPassword();
                    if (pwd != null && pwd.length() > 0) {
                        if (passwordDigest.equals(pwd)) {
                            return user;
                        }
                    }
                }
            }
        }
        return null;
    }

    private User loginByDigest(String value) throws IOException {
        Map params = parseParameters(value);
        String username = params.get("username");
        if (username != null && username.length() > 0) {
            String passwordDigest = params.get("response");
            if (passwordDigest != null && passwordDigest.length() > 0) {
                User user = getUser(username);
                if (user != null) {
                    String pwd = user.getPassword();
                    // A valid user, validate password
                    if (pwd != null && pwd.length() > 0) {
                        String uri = params.get("uri");
                        String nonce = params.get("nonce");
                        String nc = params.get("nc");
                        String cnonce = params.get("cnonce");
                        String qop = params.get("qop");
                        String method = request.getMethod();
                        String a1 = pwd;

                        String a2 = "auth-int".equals(qop)
                                ? Coder.encodeMd5(method + ":" + uri + ":" + Coder.encodeMd5(readToBytes(request.getInputStream())))
                                : Coder.encodeMd5(method + ":" + uri);
                        String digest = "auth".equals(qop) || "auth-int".equals(qop)
                                ? Coder.encodeMd5(a1 + ":" + nonce + ":" + nc + ":" + cnonce + ":" + qop + ":" + a2)
                                : Coder.encodeMd5(a1 + ":" + nonce + ":" + a2);
                        if (digest.equals(passwordDigest)) {
                            return user;
                        }
                    }
                }
            }
        }
        return null;
    }

    private boolean isLogout() {
        Cookie[] cookies = request.getCookies();
        if (cookies != null && cookies.length > 0) {
            for (Cookie cookie : cookies) {
                if (cookie != null && logoutCookie.equals(cookie.getName())) {
                    return "true".equals(cookie.getValue());
                }
            }
        }
        return false;
    }

    private void setLogout(boolean logoutValue) {
        response.addCookie(new Cookie(logoutCookie, String.valueOf(logoutValue)));
    }
}

你可能感兴趣的:(dubbo)