使用Spring Security启用HTTPS:此网页具有重定向循环

时间:2013-09-25 07:25:36

标签: tomcat ssl nginx spring-security

我正在尝试为Web应用程序上的某些页面启用HTTPS。我使用Spring MVC和Spring Security作为部署在Tomcat上的Web应用程序,使用Nginx作为tomcat的代理。

首先,没有任何HTTPS配置,一切正常。我生成了一个自签名的SSL证书并将其安装在Nginx上。我没有对Tomcat进行任何更改以启用HTTPS,因为我只想让Nginx处理SSL终止。这是我对SSL的相关Nginx配置。

         listen 443;
         server_name 127.0.0.1;
         root /usr/local/server/web/webapps/ROOT;

         ssl on;
         ssl_certificate /usr/local/etc/nginx/ssl/server.crt;
         ssl_certificate_key /usr/local/etc/nginx/ssl/server.key;


         location / {
                    proxy_pass      http://localhost:8080;
                    proxy_set_header X-Real-IP $remote_addr;
                    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                    proxy_set_header Host $http_host;
            }

我的SSL Spring安全配置如下所示:

<http pattern="/static/**" security="none" />
<http pattern="/favicon*" security="none" />

<http use-expressions="true">
    <intercept-url pattern="/login" access="permitAll" requires-channel="https" />
    <intercept-url pattern="/loginprocess" method="POST" requires-channel="https" />
    <intercept-url pattern="/logout" access="isAuthenticated()"/>
    <intercept-url pattern="/**" access="isAuthenticated()" requires-channel="https" />
    <form-login username-parameter="username"
        password-parameter="password" login-page="/login"
        login-processing-url="/loginprocess" default-target-url="/hiring"
        authentication-failure-url="/login?error" always-use-default-target="true" />
    <logout logout-url="/logout" logout-success-url="/login?logout" />
</http>

现在,当我尝试访问浏览器上的登录页面时https://localhost/internal/login,我收到错误消息 -

  

此网页有重定向循环

Spring Security中的日志如下所示:

12:34:55.240 [http-bio-8080-exec-33] DEBUG o.s.security.web.FilterChainProxy - /login at       position 1 of 10 in additional filter chain; firing Filter: 'ChannelProcessingFilter'
12:34:55.240 [http-bio-8080-exec-33] DEBUG o.s.s.web.util.AntPathRequestMatcher - Checking    match of request : '/login'; against '/login'
12:34:55.240 [http-bio-8080-exec-33] DEBUG o.s.s.w.a.c.ChannelProcessingFilter - Request: FilterInvocation: URL: /login; ConfigAttributes: [REQUIRES_SECURE_CHANNEL]
12:34:55.240 [http-bio-8080-exec-33] DEBUG o.s.s.w.a.c.RetryWithHttpsEntryPoint - Redirecting to: https://localhost/internal/login
12:34:55.241 [http-bio-8080-exec-33] DEBUG o.s.s.web.DefaultRedirectStrategy - Redirecting to 'https://localhost/internal/login'

我曾尝试过使用require-channel一段时间,但实际上并没有成功。任何帮助/指针都会很棒。

更新

我尝试使用以下配置,重定向循环错误不再存在。但是,使用这些日志进行身份验证失败 -

03:29:28.603 [http-bio-8080-exec-19] DEBUG o.s.s.w.a.c.ChannelProcessingFilter - Request:  FilterInvocation: URL: /loginprocess; ConfigAttributes: [REQUIRES_SECURE_CHANNEL]
03:29:28.603 [http-bio-8080-exec-19] DEBUG o.s.s.w.a.c.RetryWithHttpsEntryPoint - Redirecting to: https://localhost/internal/loginprocess
03:29:28.603 [http-bio-8080-exec-19] DEBUG o.s.s.web.DefaultRedirectStrategy - Redirecting to 'https://localhost/internal/loginprocess'

03:29:28.609 [http-bio-8080-exec-11] DEBUG o.s.s.web.util.AntPathRequestMatcher - Request 'GET /loginprocess' doesn't match 'POST /loginprocess
03:29:28.609 [http-bio-8080-exec-11] DEBUG o.s.s.web.util.AntPathRequestMatcher - Request '/loginprocess' matched by universal pattern '/**'

03:29:28.614 [http-bio-8080-exec-20] DEBUG o.s.security.web.FilterChainProxy - /loginprocess at position 4 of 10 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
03:29:28.614 [http-bio-8080-exec-20] DEBUG o.s.s.w.a.UsernamePasswordAuthenticationFilter - Request is to process authentication
03:29:28.615 [http-bio-8080-exec-20] DEBUG o.s.s.w.a.UsernamePasswordAuthenticationFilter - Authentication request failed:    org.springframework.security.authentication.AuthenticationServiceException: Authentication method not supported: GET

我想知道这是否是同样的问题,因为Spring Security向浏览器发送重定向并且它返回了GET请求。但是如果登录登录页面是HTTPS并且Spring因为RemoteIPValve认为它是安全的,为什么再次出现问题呢?

解决方案

我没有在RemoteIpValve中添加internalProxies参数,这导致了问题。默认情况下在internalProxies中启用了一些IP地址(在我的例子中,它是)。问题是认证是间歇性的。我为RemoteIpValve启用了日志,并观察到代理IP是IpV6格式,它与internalProxies不匹配,因此没有为该请求启用RemoteIpValve,因此出现问题。我在Mac OS X上注释掉#fe80::1%lo0 localhost行并且问题已经消失了。

顺便说一下@M中的配置。 Deinum的答案似乎运作良好。

1 个答案:

答案 0 :(得分:6)

您的HTTPS连接由NGINX处理。与应用程序的连接是HTTP连接。因此在外面基本上是安全的,内部不安全。

Spring Security使用ServletRequest中的isSecure()方法确定它是否安全,默认情况下会将协议检查为https。

当您使用tomcat时,您可以配置一个额外的阀门RemoteIpValue 3来影响isSecure()getRemoteAddr()方法(以及其他一些方法)的行为。

     <Valve
       className="org.apache.catalina.valves.RemoteIpValve"
       internalProxies="192\.168\.0\.10|192\.168\.0\.11"
       remoteIpHeader="x-forwarded-for"
       proxiesHeader="x-forwarded-by"
       protocolHeader="x-forwarded-proto"
       />

将上述内容添加到<Host >元素中(当然您可能需要删除/修改内部代理参数)。

在您的Nginx配置中添加X-Forwarded-proto标头。

location / {
    proxy_pass      http://localhost:8080;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header        X-Forwarded-Proto $scheme;
    add_header              Front-End-Https   on;
    proxy_set_header Host $http_host;
}

或者只是删除对安全通道的检查并假设一切正常......

链接

  1. ServletRequest.isSecure javadoc
  2. RemoteIpValve javadoc
  3. NGinx SSL Proxy