会话到期后,Apache代理无法通过remember-me令牌正确恢复会话

时间:2017-11-22 13:19:24

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

为什么在恢复记住我的cookie后到期后用户会话无法正常工作?

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

首先,我有一个Apache httpd服务作为代理,具有 ProxyPass 配置。我将.war作为 ROOT.war 部署,因为我想访问我的域名 www.example.com 而不指示应用名称(在其他字词上,我不想表示www.example.com/appName)

我已经阅读了很多关于这种情况的文档,我在virtal主机中的配置有以下几行:

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方法,我会遇到问题:我的控制器拒绝请求因为重新获得GET方法。

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

在本地tomcat(没有,apache代理)中,我的webapp在两种配置中都能正常工作:记住我,不记得我。

安全-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令牌,并过滤请求,因为避免了proccess paypal方法。在security-spring.xml中配置

CsrfSecurityRequestMatcher.java (我不知道这对这个问题是否重要 - &gt; 如果不是这样的话,请忽略

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;
    }
}

1 个答案:

答案 0 :(得分:0)

我最终解决了这个问题:

  1. 指向类似问题的链接:Spring Security: invalid-session-url versus logout-success-url
  2. Spring security的官方文档: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
  4.   

    [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>