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

xxslljrj  于 2023-04-12  发布在  Spring
关注(0)|答案(3)|浏览(178)

应用安全场景:

  • Spring MVC应用程序在PaaS上运行3个示例
  • 应用程序分为2个安全域。使用位于/app/kmlservice的2个DispatchServlet进行管理
  • 应用程序必须在所有页面上使用https,除了/kmlservice中的任何路径
  • 应用程序必须使用自定义登录页面访问/app中的所有路径
  • 应用程序必须使用具有LDAP身份验证的永久Remember-Me方案

当我们转换到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" />,这似乎没有什么区别
还有其他有用的配置我可以提供吗?
谢谢。

nnt7mjpx

nnt7mjpx1#

如果https终止于您的路由器,这是PaaS配置的常见情况,那么您的servlet容器需要某种方法来确定传入的请求是否实际安全。Spring Security使用标准的servlet API方法isSecure来决定是否需要重定向。我猜在您的情况下,servlet容器无法判断对路由器的外部请求是否通过HTTPS发出。
例如,Tomcat可以配置RemoteIpValve来检查特定的头部并相应地设置请求属性。我不知道你是否可以控制这一点,但你可以使用equivalent filter。当然,这也需要你知道你的PaaS是如何设置的,以及它是否会将像X-Forwarded-Proto这样的头部转发到你的应用。

xzlaal3s

xzlaal3s2#

这是一个不确定的循环,因为URL /app/login 是安全的,因为它被标记为IS_AUTHENTICATED_ANONYMOUSLY
access值更改为 permitAll

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

ru9i0ody3#

看看这个https://docs.spring.io/spring-security/reference/servlet/configuration/java.html#_multiple_httpsecurity_instances
基本上,你可以使用第一个filterChainApi和“.securityMatcher”作为你的api,使用第二个filterChainMvc和.formLogin作为你的MVC。

相关问题