美文网首页
nginx转发后,CAS拿不到正确端口的问题

nginx转发后,CAS拿不到正确端口的问题

作者: fzhyzamt | 来源:发表于2021-10-12 17:10 被阅读0次

    访问路径:用户 -> nginx -> tomcat
    在直接访问tomcat时没有问题,但经过nginx后cas无法拿到端口,导致拿到ticket后跳转错误。

    http://portal.example.com/portalcas/login;jsessionid=XXXX?service=http://example.com:8080/cas
    302 http://example.com:8080/cas?ticket=ST-1234-XXXXXX-portal.example.com
    302 http://example.com/
    

    查看cas中跳转的逻辑:

    org.apache.shiro.web.filter.authc.AuthenticationFilter
        protected void issueSuccessRedirect(ServletRequest request, ServletResponse response) throws Exception {
            WebUtils.redirectToSavedRequest(request, response, getSuccessUrl());
        }
    org.apache.shiro.web.util.WebUtils
        public static void issueRedirect(ServletRequest request, ServletResponse response, String url, Map queryParams, boolean contextRelative, boolean http10Compatible) throws IOException {
            RedirectView view = new RedirectView(url, contextRelative, http10Compatible);
            view.renderMergedOutputModel(queryParams, toHttp(request), toHttp(response));
        }
    org.apache.shiro.web.servlet.ShiroHttpServletResponse
        public String encodeRedirectURL(String url) {
            if (isEncodeable(toAbsolute(url))) {
                return toEncoded(url, request.getSession().getId());
            } else {
                return url;
            }
        }
        private String toAbsolute(String location) {
            boolean leadingSlash = location.startsWith("/");
    
            if (leadingSlash || !hasScheme(location)) {
    
                StringBuilder buf = new StringBuilder();
    
                String scheme = request.getScheme();
                String name = request.getServerName();
                int port = request.getServerPort();
    
                try {
                    buf.append(scheme).append("://").append(name);
                    if ((scheme.equals("http") && port != 80)
                            || (scheme.equals("https") && port != 443)) {
                        buf.append(':').append(port);
                    }
                    if (!leadingSlash) {
                        String relativePath = request.getRequestURI();
                        int pos = relativePath.lastIndexOf('/');
                        relativePath = relativePath.substring(0, pos);
    
                        String encodedURI = URLEncoder.encode(relativePath, getCharacterEncoding());
                        buf.append(encodedURI).append('/');
                    }
                    buf.append(location);
                } catch (IOException e) {
                    IllegalArgumentException iae = new IllegalArgumentException(location);
                    iae.initCause(e);
                    throw iae;
                }
    
                return buf.toString();
    
            } else {
                return location;
            }
        }
    

    其中的request.getServerPort();是获取请求头中的端口,如果nginx转发时没有带上就会是默认的80

    方案一

    不推荐
    nginx中将proxy_set_header Host $host;改为proxy_set_header Host $host:$server_port;proxy_set_header Host $http_host;

    方案二

    nginx中添加如下头:

    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Host $server_addr;
    proxy_set_header X-Forwarded-Port $server_port;
    proxy_set_header X-Forwarded-Proto $scheme;
    

    如果是springboot集成的tomcat,在application.yml中如下配置:

    server:
      tomcat:
        remoteip:
          protocol-header: X-Forwarded-Proto
          remote-ip-header: X-Forwarded-For
          protocol-header-https-value: https
    

    如果直接配置tomcat的xml:

    <Engine>
        <Valve className="org.apache.catalina.valves.RemoteIpValve" 
        remoteIpHeader="X-Forwarded-For" 
        protocolHeader="X-Forwarded-Proto" 
        protocolHeaderHttpsValue="https"/>
    </Engine >
    

    当开启了X-Forwarded-Proto时,会去获取X-Forwarded-Port的值,获取不到就会使用默认的80、443.

    参考:
    https://serverfault.com/questions/363159/nginx-proxy-pass-redirects-ignore-port
    http://thomaslau.xyz/2019/10/28/2019-10-28-nginx_springsecurity_cas_error/
    https://blog.csdn.net/goldenfish1919/article/details/78815192
    https://blog.csdn.net/heavenick/article/details/51924774

    相关文章

      网友评论

          本文标题:nginx转发后,CAS拿不到正确端口的问题

          本文链接:https://www.haomeiwen.com/subject/foxjoltx.html