【问题标题】:Apache proxy does not recover session correctly by remember-me token after the session expires会话过期后,Apache 代理无法通过记住我的令牌正确恢复会话
【发布时间】:2017-11-27 04:15:38
【问题描述】:

为什么在恢复 remember-me cookie 后过期后用户会话不能正常工作?

我在 Spring Security 中启用了 remember-me 选项时遇到了一个特殊错误。当会话到期时,我可以浏览我的其余网页,但注销和其他 POST 方法会在服务器中产生错误。它们不起作用,因为我的控制器接收的是 GET 方法而不是 POST。我不明白为什么。

首先,我有一个具有 ProxyPass 配置的 Apache httpd 服务作为代理。我将 .war 部署为 ROOT.war 因为我想访问我的域 www.example.com 而不指明应用程序名称(换句话说,我不想指明www.example.com/appName)

我已经阅读了很多关于这个案例的文档,我在虚拟主机中的配置有以下几行:

ProxyRequests Off
<Proxy *>
    Order deny,allow
    Allow from all
</Proxy>

ProxyPass / http://example.com:9080/
ProxyPassReverse / http://example.com:9080/

<Location />
    Order allow,deny
    Allow from all
</Location>

#FIX For Spring Security
RewriteEngine on
RewriteRule ^/(.*)$ http://example.com:9080/$1 [P,L]

在使用表单进行正常身份验证后,post 方法需要修复 Spring Scurity 指令。

问题

在 JSSESIONID cookie 过期之前,我可以正确使用该应用程序:我可以注销,我可以使用其他方法 post 等...这里没有问题。但是当会话到期时,任何东西都会被破坏。我可以浏览网页,访问信息,并且永远不会重定向到登录页面进行身份验证(我知道 remember-me cockie 有效),但如果我使用 POST 方法,我会遇到问题:我的控制器拒绝该请求是因为接收了一个 GET 方法。

我在相同的环境中测试了应用程序,但在 security-context.xml 中禁用了记住我的配置,部署 ROOT.war,并在会话到期时测试应用程序......并且.....我被重定向到登录页面正确。

在本地 tomcat(没有 apache 代理)中,我的 webapp 在两种配置中都能正常工作:使用 remember-me 和没有 remember-me。

security-context.xml

<bean id="csrfSecurityRequestMatcher" class="com.XXX.YYY.config.CsrfSecurityRequestMatcher"></bean>

<security:form-login 
            authentication-success-handler-ref="customAuthenticationSuccessHandler"
            authentication-failure-url="/login?error"
            login-page="/login"
            password-parameter="lgPassword" 
            username-parameter="lgUsername" />

        <security:logout
            success-handler-ref="customLogoutSuccessHandler" 
            logout-url="/logout"
            invalidate-session="true" />

        <security:csrf
            request-matcher-ref="csrfSecurityRequestMatcher" 
            disabled="false" />

        <security:remember-me
            user-service-ref="customUserDetailsService"
            token-repository-ref="customPersistentTokenRepository"
            remember-me-parameter="lgRememberMe"
            remember-me-cookie="TRMMBRM" 
            token-validity-seconds="7776000" />

        <security:session-management>
            <security:concurrency-control 
                max-sessions="1"
                expired-url="/login" />
        </security:session-management>

web.xml(在我看来,配置对于这种情况更重要......)

...
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
...
<filter>
    <display-name>springSecurityFilterChain</display-name>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<!-- Session Configuration-->
<session-config>
    <session-timeout>1</session-timeout> <!-- (in minutes (1 min for test) --> 
</session-config>

  • JVM 版本:1.8.0_151-b12
  • Spring MVC 4.3.5.RELEASE
  • Spring Security 4.2.1.RELEASE
  • Apache/2.4.6 (CentOS)
  • Apache Tomcat/7.0.76

我也为方法启用了 CSRF 令牌,并过滤请求,因为避免处理 paypal 方法。 security-spring.xml中的配置

CsrfSecurityRequestMatcher.java(我不知道这对这个问题是否重要 -> 如果不需要,请忽略

package com.XXX.YYY.config;

import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;

public class CsrfSecurityRequestMatcher implements RequestMatcher {
    private Pattern allowedMethods = Pattern.compile("^(GET|HEAD|TRACE|OPTIONS)$");

    // Deshabilitamos la protección CSRF de las siguientes URLs:
    private AntPathRequestMatcher[] requestMatchers = { new AntPathRequestMatcher("/paypal/**") };

    @Override
    public boolean matches(HttpServletRequest request) {          
        if(allowedMethods.matcher(request.getMethod()).matches()){
            return false;
        }

        // Si la peticion coincide con el patrón a ignorar deshabilitamos la protección CSRF
        for (AntPathRequestMatcher rm : requestMatchers) {
          if (rm.matches(request)) { return false; }
        }

        return true;
    }
}

【问题讨论】:

    标签: apache spring-security proxy tomcat7 remember-me


    【解决方案1】:

    我终于解决了这个问题:

    1. 类似问题的链接:Spring Security: invalid-session-url versus logout-success-url
    2. Spring安全官方文档:https://docs.spring.io/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#ns-session-mgmt
    3. 看笔记[8] https://docs.spring.io/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#ftn.d0e1047

    [8] 如果您在代理后面运行应用程序,您还可以 可以通过配置代理服务器来删除会话cookie。

    <LocationMatch "/tutorial/j_spring_security_logout">
    Header always set Set-Cookie "JSESSIONID=;Path=/tutorial;Expires=Thu, 01 Jan 1970 00:00:00 GMT"
    </LocationMatch>
    

    【讨论】:

      猜你喜欢
      • 2016-09-26
      • 2019-07-04
      • 1970-01-01
      • 2018-03-16
      • 1970-01-01
      • 2012-05-29
      • 2015-12-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多