title: Spring Boot container authentication with standalone Tomcat
body: <p>I have a standalone Tomcat server which should run my Spring Boot application (deployed as a <code>.war</code> file). This application needs to be secured with container authentication from Tomcat. First it should use the <code>tomcat-users.xml</code> in the development environment. In the production environment this realm will be replaced by another authentication method.</p>
  
  <p>My configuration:</p>
  
  <pre class="lang-java prettyprint-override"><code>@Configuration
  @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
  @EnableGlobalMethodSecurity(prePostEnabled = true)
  public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
  
      @Override
      protected void configure(HttpSecurity http) throws Exception {
          http.httpBasic().disable()
              .authorizeRequests()
                  .antMatchers("/test/test2").permitAll()
                  .anyRequest().authenticated()
              .and()
                  .formLogin().permitAll()
              .and()
                  .logout().permitAll()
              .and()
                  .jee().mappableRoles("USER");
      }
  
  }
  </code></pre>
  
  <p>Tomcat users:</p>
  
  <pre class="lang-xml prettyprint-override"><code>&lt;?xml version='1.0' encoding='utf-8'?&gt;
  &lt;tomcat-users xmlns="http://tomcat.apache.org/xml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://tomcat.apache.org/xml tomcat-users.xsd" version="1.0"&gt;
      &lt;user username="testuser" password="pw" roles="user" /&gt;
  &lt;/tomcat-users&gt;
  </code></pre>
  
  <p>On secured pages the form login appears like expected, but the authentication does not work (Your login attempt was not successful, try again.).</p>
  
  <p>Is something else missing in the configuration?</p>
  
  <p>Log:</p>
  
  <pre><code>09:53:40 DEBUG o.s.security.web.FilterChainProxy        : /login at position 1 of 13 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
  09:53:40 DEBUG o.s.security.web.FilterChainProxy        : /login at position 2 of 13 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
  09:53:40 DEBUG w.c.HttpSessionSecurityContextRepository : HttpSession returned null object for SPRING_SECURITY_CONTEXT
  09:53:40 DEBUG w.c.HttpSessionSecurityContextRepository : No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@22ea93f6. A new one will be created.
  09:53:40 DEBUG o.s.security.web.FilterChainProxy        : /login at position 3 of 13 in additional filter chain; firing Filter: 'HeaderWriterFilter'
  09:53:40 DEBUG o.s.s.w.header.writers.HstsHeaderWriter  : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@738151d2
  09:53:40 DEBUG o.s.security.web.FilterChainProxy        : /login at position 4 of 13 in additional filter chain; firing Filter: 'LogoutFilter'
  09:53:40 DEBUG o.s.s.web.util.matcher.OrRequestMatcher  : Trying to match using Ant [pattern='/logout', GET]
  09:53:40 DEBUG o.s.s.w.u.matcher.AntPathRequestMatcher  : Request 'POST /login' doesn't match 'GET /logout
  09:53:40 DEBUG o.s.s.web.util.matcher.OrRequestMatcher  : Trying to match using Ant [pattern='/logout', POST]
  09:53:40 DEBUG o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/login'; against '/logout'
  09:53:40 DEBUG o.s.s.web.util.matcher.OrRequestMatcher  : Trying to match using Ant [pattern='/logout', PUT]
  09:53:40 DEBUG o.s.s.w.u.matcher.AntPathRequestMatcher  : Request 'POST /login' doesn't match 'PUT /logout
  09:53:40 DEBUG o.s.s.web.util.matcher.OrRequestMatcher  : Trying to match using Ant [pattern='/logout', DELETE]
  09:53:40 DEBUG o.s.s.w.u.matcher.AntPathRequestMatcher  : Request 'POST /login' doesn't match 'DELETE /logout
  09:53:40 DEBUG o.s.s.web.util.matcher.OrRequestMatcher  : No matches found
  09:53:40 DEBUG o.s.security.web.FilterChainProxy        : /login at position 5 of 13 in additional filter chain; firing Filter: 'J2eePreAuthenticatedProcessingFilter'
  09:53:40 DEBUG p.j.J2eePreAuthenticatedProcessingFilter : Checking secure context token: null
  09:53:40 DEBUG p.j.J2eePreAuthenticatedProcessingFilter : PreAuthenticated J2EE principal: null
  09:53:40 DEBUG p.j.J2eePreAuthenticatedProcessingFilter : No pre-authenticated principal found in request
  09:53:40 DEBUG o.s.security.web.FilterChainProxy        : /login at position 6 of 13 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
  09:53:40 DEBUG o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/login'; against '/login'
  09:53:40 DEBUG w.a.UsernamePasswordAuthenticationFilter : Request is to process authentication
  09:53:40 DEBUG o.s.s.authentication.ProviderManager     : Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider
  09:53:40 DEBUG o.s.s.a.dao.DaoAuthenticationProvider    : User 'testuser' not found
  09:53:40 DEBUG o.s.b.f.s.DefaultListableBeanFactory     : Returning cached instance of singleton bean 'delegatingApplicationListener'
  09:53:40 DEBUG w.a.UsernamePasswordAuthenticationFilter : Authentication request failed: org.springframework.security.authentication.BadCredentialsException: Bad credentials
  </code></pre>