Why dont work correctly the user session when this expires after recover remember-me cookie?
I have a peculiar error with I enable the remember-me option in Spring Security. When the session expire, I can navigate for the rest of my web pages, but the logout, and the others POST methods produce a error in server. They doesnt work, because my controllers recive a GET method instead of POST. I dont understand why.
First, I have a Apache httpd serve working as proxy, with ProxyPass configuration. I deployed my .war as ROOT.war because I want to access to my domain www.example.com without indicates the app name (on others words, I dont want indicates www.example.com/appName)
I has read a lot of documentation about this case, and my configuration in virtal host has the following lines:
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]
The fix for Spring Scurity directives are neccessary for post methods after normal authentication using form.
The problem
Before the JSSESIONID cookie expires, I can use the application correctly: I can logout, I can use other method post, etc...no problems here. But when session expires, anything is broked. I can move through the web pages, access to information, and never I am redirect to login page for authentication (I understand that the remember-me cockie works), but if I use a POST method, I get a problem: my controllers refuse the request because recives a GET method.
I tested the app into same enviroment, but disabled remember-me configuration in security-context.xml, deploy ROOT.war, and test the app when session expires... and..... I am redirect to login page correctly.
In local tomcat (without, apache proxy), my webapp work correctly in both configuration: with remember-me and without 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 (config more important for this case in my opinion...)
...
<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>
I have enable CSRF token too for methods, and filters request because avoid proccess paypal methods. Configuration in security-spring.xml
CsrfSecurityRequestMatcher.java (I dont know if this is important for this problem -> ignore if this is not neccessary)
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;
}
}
I resolved this problem finally:
[8] If you are running your application behind a proxy, you may also be able to remove the session cookie by configuring the proxy server.
<LocationMatch "/tutorial/j_spring_security_logout"> Header always set Set-Cookie "JSESSIONID=;Path=/tutorial;Expires=Thu, 01 Jan 1970 00:00:00 GMT" </LocationMatch>