title: Apache proxy does not recover session correctly by remember-me token after the session expires
body: <p><strong>Why dont work correctly the user session when this expires after recover remember-me cookie?</strong></p>
  
  <p>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.</p>
  
  <p>First, I have a Apache httpd serve working as proxy, with <strong>ProxyPass</strong> configuration. I deployed my .war as <strong>ROOT.war</strong> because I want to access to my domain <strong>www.example.com</strong> without indicates the app name (on others words, I dont want indicates www.example.com/appName)</p>
  
  <p>I has read a lot of documentation about this case, and my configuration in virtal host has the following lines:</p>
  
  <pre><code>ProxyRequests Off
  &lt;Proxy *&gt;
      Order deny,allow
      Allow from all
  &lt;/Proxy&gt;
  
  ProxyPass / http://example.com:9080/
  ProxyPassReverse / http://example.com:9080/
  
  &lt;Location /&gt;
      Order allow,deny
      Allow from all
  &lt;/Location&gt;
  
  #FIX For Spring Security
  RewriteEngine on
  RewriteRule ^/(.*)$ http://example.com:9080/$1 [P,L]
  </code></pre>
  
  <p>The fix for Spring Scurity directives are neccessary for post methods after normal authentication using form.</p>
  
  <p><strong>The problem</strong></p>
  
  <p>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 <strong>when session expires, anything is broked</strong>. 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.</p>
  
  <p>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.</p>
  
  <p>In local tomcat (without, apache proxy), my webapp work correctly in both configuration: with remember-me and without remember-me.</p>
  
  <p><strong>security-context.xml</strong></p>
  
  <pre><code>&lt;bean id="csrfSecurityRequestMatcher" class="com.XXX.YYY.config.CsrfSecurityRequestMatcher"&gt;&lt;/bean&gt;
  
  &lt;security:form-login 
              authentication-success-handler-ref="customAuthenticationSuccessHandler"
              authentication-failure-url="/login?error"
              login-page="/login"
              password-parameter="lgPassword" 
              username-parameter="lgUsername" /&gt;
  
          &lt;security:logout
              success-handler-ref="customLogoutSuccessHandler" 
              logout-url="/logout"
              invalidate-session="true" /&gt;
  
          &lt;security:csrf
              request-matcher-ref="csrfSecurityRequestMatcher" 
              disabled="false" /&gt;
  
          &lt;security:remember-me
              user-service-ref="customUserDetailsService"
              token-repository-ref="customPersistentTokenRepository"
              remember-me-parameter="lgRememberMe"
              remember-me-cookie="TRMMBRM" 
              token-validity-seconds="7776000" /&gt;
  
          &lt;security:session-management&gt;
              &lt;security:concurrency-control 
                  max-sessions="1"
                  expired-url="/login" /&gt;
          &lt;/security:session-management&gt;
  </code></pre>
  
  <p><strong>web.xml</strong> (config more important for this case in my opinion...)</p>
  
  <pre><code>...
  &lt;listener&gt;
      &lt;listener-class&gt;org.springframework.web.context.ContextLoaderListener&lt;/listener-class&gt;
  &lt;/listener&gt;
  ...
  &lt;filter&gt;
      &lt;display-name&gt;springSecurityFilterChain&lt;/display-name&gt;
      &lt;filter-name&gt;springSecurityFilterChain&lt;/filter-name&gt;
      &lt;filter-class&gt;org.springframework.web.filter.DelegatingFilterProxy&lt;/filter-class&gt;
  &lt;/filter&gt;
  
  &lt;filter-mapping&gt;
      &lt;filter-name&gt;springSecurityFilterChain&lt;/filter-name&gt;
      &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
  &lt;/filter-mapping&gt;
  
  &lt;!-- Session Configuration--&gt;
  &lt;session-config&gt;
      &lt;session-timeout&gt;1&lt;/session-timeout&gt; &lt;!-- (in minutes (1 min for test) --&gt; 
  &lt;/session-config&gt;
  </code></pre>
  
  <hr>
  
  <ul>
  <li>JVM Version: 1.8.0_151-b12</li>
  <li>Spring MVC 4.3.5.RELEASE</li>
  <li>Spring Security 4.2.1.RELEASE</li>
  <li>Apache/2.4.6 (CentOS)</li>
  <li>Apache Tomcat/7.0.76</li>
  </ul>
  
  <p>I have enable CSRF token too for methods, and filters request because avoid proccess paypal methods. Configuration in security-spring.xml</p>
  
  <p><strong>CsrfSecurityRequestMatcher.java</strong> (I dont know if this is important for this problem -> <strong>ignore if this is not neccessary</strong>)</p>
  
  <pre><code>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;
      }
  }
  </code></pre>