为什么在恢复记住我的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>
我也为方法启用了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;
}
}
答案 0 :(得分:0)
我最终解决了这个问题:
[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>