使用自定义表单登录时如何避免Spring Security重定向循环?

时间:2014-05-27 19:58:15

标签: spring-security

应用安全方案:

  • Spring MVC应用程序在PaaS上运行3个实例
  • 应用程序分为2个安全域。托管w / 2 DispatchServlet位于/app/kmlservice
  • /kmlservice
  • 中的任何路径外,应用必须在所有网页上使用https
  • 应用必须使用自定义登录页面才能访问/app
  • 中的所有路径
  • 应用必须使用具有LDAP身份验证的持久记住我方案

当我们转换为https时,我们在尝试导航到/app/login页面或任何其他页面时获得无限重定向循环。事实上,即使是不受保护的页面也会无限地重新路由自己。

以下是我们在尝试导航到/app/login时看到的重定向日志示例:

stdout.log: DEBUG: org.springframework.security.web.access.channel.ChannelProcessingFilter - Request: FilterInvocation: URL: /app/login; ConfigAttributes: [REQUIRES_SECURE_CHANNEL]
stdout.log: DEBUG: org.springframework.security.web.access.channel.RetryWithHttpsEntryPoint - Redirecting to: https:/some_url.com/app/login
stdout.log: DEBUG: org.springframework.security.web.DefaultRedirectStrategy - Redirecting to 'https:/some_url.com/app/login'
stdout.log: DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/app/login'; against '/kmlservice/**'
stdout.log: DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/app/login'; against '/resources/**'
stdout.log: DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/app/login'; against '/app/**'
stdout.log: DEBUG: org.springframework.security.web.FilterChainProxy - /app/login at position 1 of 12 in additional filter chain; firing Filter: 'ChannelProcessingFilter'
stdout.log: DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/app/login'; against '/app/logout'
stdout.log: DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/app/login'; against '/app/accessdenied'
stdout.log: DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/app/login'; against '/app/useful_path'
stdout.log: DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/app/login'; against '/app/help'
stdout.log: DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/app/login'; against '/app/login'
stdout.log: DEBUG: org.springframework.security.web.access.channel.ChannelProcessingFilter - Request: FilterInvocation: URL: /app/login; ConfigAttributes: [REQUIRES_SECURE_CHANNEL]
stdout.log: DEBUG: org.springframework.security.web.access.channel.RetryWithHttpsEntryPoint - Redirecting to: https:/some_url.com/app/login
stdout.log: DEBUG: org.springframework.security.web.DefaultRedirectStrategy - Redirecting to 'https:/some_url.com/app/login'

这是配置的样子:

<http pattern="/kmlservice/**" use-expressions="true" auto-config="true">
    <intercept-url pattern="/**" access="isAuthenticated()" />
    <http-basic />
</http>

<http pattern="/resources/**" security="none" />

<http pattern="/app/**" use-expressions="true">
    <form-login login-page="/app/login"
        authentication-failure-url="/app/accessdenied" default-target-url="/app" />
    <intercept-url pattern="/app/logout" access="permitAll"
        requires-channel="https" />
    <intercept-url pattern="/app/accessdenied" access="permitAll"
        requires-channel="https" />
    <intercept-url pattern="/app/useful_path"
        access="hasRole('ROLE_HAS_ACCESS')" requires-channel="https" />
    <intercept-url pattern="/app/help" access="permitAll"
        requires-channel="https" />
    <intercept-url pattern="/app/login" access="IS_AUTHENTICATED_ANONYMOUSLY"
        requires-channel="https" />
    <intercept-url pattern="/app/**" access="isAuthenticated()"
        requires-channel="https" />
    <access-denied-handler error-page="/403" />
    <logout logout-success-url="/app/logout" delete-cookies="JSESSIONID" />
    <remember-me user-service-ref="userDetailsService"
        data-source-ref="dataSource" />
</http>

我试图删除 <intercept-url pattern="/app/**" access="isAuthenticated()" requires-channel="https" /> 这似乎没什么区别

我能提供其他有用的配置吗? 感谢。

2 个答案:

答案 0 :(得分:1)

如果https终止于您的路由器,就像PaaS配置的情况一样,那么您的servlet容器需要一些方法来确定传入请求是否确实是安全的。 Spring Security使用标准servlet API方法isSecure来决定是否需要重定向。我想在你的情况下,servlet容器无法判断对路由器的外部请求是否是通过HTTPS进行的。

例如,可以使用RemoteIpValve配置Tomcat以检查特定标头并相应地设置请求属性。我不知道你是否对此有任何控制权,但是你可以使用equivalent filter代替它。当然,这也要求您了解PaaS的设置方式以及是否将X-Forwarded-Proto之类的标题转发到您的应用中。

答案 1 :(得分:1)

它会无限循环,因为URL / app / login 是安全的,因为它标有IS_AUTHENTICATED_ANONYMOUSLY

access值更改为 permitAll

<intercept-url pattern="/app/login" access="permitAll" requires-channel="https" />