Spring Security - 405 error when calling login-processing-url

I have sprinc core + spring mvc + protection and work using XML configuration, and these are the versions that I use in my pom.xml:

<spring.version>4.0.1.RELEASE</spring.version>
<spring.security.version>3.2.0.RELEASE</spring.security.version>

So, I decided to go and move my whole xml configuration to java configuration. What happens is that the login password for spring protection stops working and now gives me a 405 error saying that POST is not allowed. For example, this is my spring security xml file:

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
   xmlns:context="http://www.springframework.org/schema/context"
   xmlns:util="http://www.springframework.org/schema/util"
   xmlns:p="http://www.springframework.org/schema/p" 
   xmlns="http://www.springframework.org/schema/security"
   xsi:schemaLocation="http://www.springframework.org/schema/beans      http://www.springframework.org/schema/beans/spring-beans-4.0.xsd 
                   http://www.springframework.org/schema/context    http://www.springframework.org/schema/context/spring-context-4.0.xsd
                   http://www.springframework.org/schema/util       http://www.springframework.org/schema/util/spring-util-4.0.xsd
                       http://www.springframework.org/schema/security   http://www.springframework.org/schema/security/spring-security-3.2.xsd">

<!-- Satic content -->
<http pattern="/assets/**" security="none" />
<http pattern="/css/**" security="none" />
<http pattern="/img/**" security="none" />
<http pattern="/js/**" security="none" />

<!--http://docs.spring.io/spring-security/site/docs/3.2.0.RELEASE/reference/htmlsingle/#ns-global-method-->
<global-method-security pre-post-annotations="enabled" />

<!-- Protected Requests -->
<http auto-config="true" use-expressions="true" authentication-manager-ref="authenticationManager">

    <intercept-url pattern="/login/**" access="permitAll" />
    <intercept-url pattern="/api/**" access="permitAll" />
    <intercept-url pattern="/**" access="isRememberMe() or isFullyAuthenticated()" />

    <form-login login-processing-url="/loginCheck"
        login-page="/login" 
        authentication-failure-url="/loginFailure" 
        default-target-url="/" 
        always-use-default-target="true" 
        password-parameter="password"
        username-parameter="username"/>

    <logout delete-cookies="JSESSIONID" logout-url="/logout" logout-success-url="/login" />
    <access-denied-handler error-page="/403" />

    <session-management invalid-session-url="/login" session-fixation-protection="newSession" />

    <headers>
        <frame-options/>
        <xss-protection/>
    </headers>

    <remember-me services-ref="rememberMeServices" />
</http> 

<authentication-manager alias="authenticationManager">
    <authentication-provider ref="mongoDashAuthenticationProvider" />
    <authentication-provider ref="rememberMeAuthenticationProvider" />
</authentication-manager>

<beans:bean id="rememberMeServices" class="org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices">
    <beans:constructor-arg value="${security.app.key}" />
    <beans:constructor-arg ref="userServiceImpl" />
    <beans:constructor-arg ref="mongoDashPersistentTokenRepository" />
    <beans:property name="tokenValiditySeconds" value="172800" />
    <beans:property name="parameter" value="remember" />
    <beans:property name="cookieName" value="REMEMBER_ME" />
</beans:bean>

<beans:bean id="rememberMeAuthenticationProvider" class="org.springframework.security.authentication.RememberMeAuthenticationProvider" >
    <beans:property name="key" value="${security.app.key}" />
</beans:bean>

<!-- Way better than SHA -->
<beans:bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
    <beans:constructor-arg name="strength" value="15" /> 
</beans:bean>

and this is my spring java configuration file for spring security:

@Configuration
@EnableWebMvcSecurity
@PropertySource("classpath:app.properties")
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Value("${security.app.key}")
String appKey;

@Autowired
UserService userService;

@Autowired
MongoDashPersistentTokenRepository mongoDashPersistentTokenRepository;

@Autowired
public void registerGlobalAuthentication(AuthenticationManagerBuilder auth) throws Exception {
    auth
        .eraseCredentials(true)
        .authenticationProvider(new MongoDashAuthenticationProvider())
        .authenticationProvider(rememberMeAuthenticationProvider());
        //.build();

    /**
    <authentication-manager alias="authenticationManager">
        <authentication-provider ref="mongoDashAuthenticationProvider" />
        <authentication-provider ref="rememberMeAuthenticationProvider" />
    </authentication-manager>
     */
}

@Override
public void configure(WebSecurity web) throws Exception {
    web
        .ignoring()
            .antMatchers("/assets/**")
            .antMatchers("/css/**")
            .antMatchers("/img/**")
            .antMatchers("/js/**")
            .antMatchers("/fonts/**");
    /**
    <http pattern="/assets/**" security="none" />
    <http pattern="" security="none" />
    <http pattern="" security="none" />
    <http pattern="" security="none" /> 
    **/
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http    

        .headers()
            .xssProtection()
            .frameOptions()
            .and()
        .authorizeRequests()
            .antMatchers("/login/**").permitAll()
            .antMatchers("/api/**").permitAll()
            .antMatchers("/**").access("isRememberMe() or isFullyAuthenticated()")
            .and()
        .formLogin()
            .loginProcessingUrl("/loginCheck")
            .loginPage("/login")
            //.failureUrl("/loginFailure")
            .defaultSuccessUrl("/", true)
            .passwordParameter("password")
            .usernameParameter("username")
            .permitAll()
            .and()
        .logout()
            .logoutSuccessUrl("/login")
            .logoutUrl("/logout")
            .deleteCookies("JSESSIONID")
            .and()
        .sessionManagement()
            .invalidSessionUrl("/login")
            .sessionFixation().newSession()
            .and()
        .exceptionHandling()
            .accessDeniedPage("/403")
            .and()
        .rememberMe()
            .rememberMeServices(rememberMeServices());


}

@Bean
public RememberMeAuthenticationProvider rememberMeAuthenticationProvider() {
    RememberMeAuthenticationProvider provider = new RememberMeAuthenticationProvider(appKey);
    return provider;

    /**
    <beans:bean id="rememberMeAuthenticationProvider" class="org.springframework.security.authentication.RememberMeAuthenticationProvider" >
        <beans:property name="key" value="${security.app.key}" />
    </beans:bean>
    **/
}

@Bean
public PersistentTokenBasedRememberMeServices rememberMeServices() {
    PersistentTokenBasedRememberMeServices rememberMeServices = new PersistentTokenBasedRememberMeServices(appKey, userService,
            mongoDashPersistentTokenRepository);
    rememberMeServices.setCookieName("REMEMBER_ME");
    rememberMeServices.setParameter("remember");
    rememberMeServices.setTokenValiditySeconds(172800);
    return rememberMeServices;

    /**
    <beans:bean id="rememberMeServices" class="org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices">
        <beans:constructor-arg value="${security.app.key}" />
        <beans:constructor-arg ref="userServiceImpl" />
        <beans:constructor-arg ref="mongoDashPersistentTokenRepository" />
        <beans:property name="tokenValiditySeconds" value="172800" />
        <beans:property name="parameter" value="remember" />
        <beans:property name="cookieName" value="REMEMBER_ME" />
    </beans:bean>
    **/
}

@Bean
public BCryptPasswordEncoder passwordEncoder() {

    BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(15);
    return passwordEncoder;

    /**
    <beans:bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
        <beans:constructor-arg name="strength" value="15" /> 
    </beans:bean>
     **/
}
}

And this is my appconfig

@Configuration
@Import({SecurityConfig.class})
//@ImportResource("classpath:spring/security-context.xml")
@ComponentScan(basePackages = { "com.mongom" }, excludeFilters = {      @ComponentScan.Filter(Controller.class),
    @ComponentScan.Filter(Configuration.class) })
@PropertySource(value = { "classpath:app.properties" })
@EnableMBeanExport
@EnableAspectJAutoProxy
public class AppConfig {

@Bean
public MessageSource messageSource() {
    ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
    messageSource.setBasenames("validation", "messages");
    return messageSource;
}

@Bean
public PropertiesFactoryBean properties() {
    PropertiesFactoryBean ppc = new PropertiesFactoryBean();
    ppc.setLocations(new Resource[] { new ClassPathResource("app.properties") });
    ppc.setIgnoreResourceNotFound(false);
    return ppc;
}

 }

web.xml

<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

<display-name>MongoDASH</display-name>

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

   <context-param>
        <param-name>contextClass</param-name>
    <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>com.mongom.spring.AppConfig</param-value>
</context-param>    

<servlet>
    <servlet-name>mongodash</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextClass</param-name>
        <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
    </init-param>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>com.mongom.spring.WebConfig</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>


<servlet-mapping>
    <servlet-name>mongodash</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

<!-- Spring Security -->

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

<env-entry>
    <description>JNDI logging context for this app</description>
    <env-entry-name>logback/contextName</env-entry-name>
    <env-entry-type>java.lang.String</env-entry-type>
    <env-entry-value>mongom</env-entry-value>
</env-entry>

<welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
</welcome-file-list>

<error-page>
    <error-code>400</error-code>
    <location>/404</location>
</error-page>

<error-page>
    <error-code>404</error-code>
    <location>/404</location>
</error-page>

<error-page>
    <error-code>403</error-code>
    <location>/403</location>
</error-page>

<error-page>
    <error-code>500</error-code>
    <location>/500</location>
</error-page>

Console output:

02/06 11:53:26.678 [http-bio-8080-exec-7] WARN  o.s.web.servlet.PageNotFound Request method 'POST' not supported
02/06 11:53:50.023 [http-bio-8080-exec-5] WARN  o.s.web.servlet.PageNotFound Request method 'POST' not supported
02/06 11:53:53.408 [http-bio-8080-exec-5] WARN  o.s.web.servlet.PageNotFound Request method 'POST' not supported
02/06 11:53:55.504 [http-bio-8080-exec-5] WARN  o.s.web.servlet.PageNotFound Request method 'POST' not supported

Login form:

<form class="form-signin" action="loginCheck" method="POST">
    <h2 class="form-signin-heading">sign in now</h2>
    <div class="login-wrap">
        <input type="text" name="username" class="form-control" placeholder="User ID" autofocus value="guest" />
        <input type="password" name="password" class="form-control" placeholder="Password" value="!Guest2014!" />
        <label class="checkbox">
            <input type="checkbox" name="remember" />Remember me
            <span class="pull-right">
                <a data-toggle="modal" href="#myModal"> Forgot Password?</a>
            </span>
        </label>
        <button class="btn btn-lg btn-login btn-block" type="submit">Sign in</button>
    </div>
 </form>

Spring Security Logs:

02/06 15:57:34.202 [localhost-startStop-1] INFO  o.s.s.web.DefaultSecurityFilterChain Creating filter chain: Ant [pattern='/assets/**'], []
02/06 15:57:34.202 [localhost-startStop-1] INFO  o.s.s.web.DefaultSecurityFilterChain Creating filter chain: Ant [pattern='/css/**'], []
02/06 15:57:34.203 [localhost-startStop-1] INFO  o.s.s.web.DefaultSecurityFilterChain Creating filter chain: Ant [pattern='/img/**'], []
02/06 15:57:34.203 [localhost-startStop-1] INFO  o.s.s.web.DefaultSecurityFilterChain Creating filter chain: Ant [pattern='/js/**'], []
02/06 15:57:34.203 [localhost-startStop-1] INFO  o.s.s.web.DefaultSecurityFilterChain Creating filter chain: Ant [pattern='/fonts/**'], []
02/06 15:57:34.264 [localhost-startStop-1] INFO  o.s.s.web.DefaultSecurityFilterChain Creating filter chain: org.springframework.security.web.util.matcher.AnyRequestMatcher@1, [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@28562791, org.springframework.security.web.context.SecurityContextPersistenceFilter@1f33b16a, org.springframework.security.web.header.HeaderWriterFilter@12504e0, org.springframework.security.web.csrf.CsrfFilter@7ff12373, org.springframework.security.web.authentication.logout.LogoutFilter@40e9e799, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@334362d9, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@892b7c2, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@d0da1d8, org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter@5eba06ff, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@303fb547, org.springframework.security.web.session.SessionManagementFilter@a5ae1e7, org.springframework.security.web.access.ExceptionTranslationFilter@13883d5f, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@52ecba8]

Spring security when submitting a login form:

    02/06 17:04:33.642 [http-bio-8080-exec-10] DEBUG o.s.s.w.u.m.AntPathRequestMatcher Checking match of request : '/logincheck'; against '/assets/**'
02/06 17:04:33.643 [http-bio-8080-exec-10] DEBUG o.s.s.w.u.m.AntPathRequestMatcher Checking match of request : '/logincheck'; against '/css/**'
02/06 17:04:33.644 [http-bio-8080-exec-10] DEBUG o.s.s.w.u.m.AntPathRequestMatcher Checking match of request : '/logincheck'; against '/img/**'
02/06 17:04:33.644 [http-bio-8080-exec-10] DEBUG o.s.s.w.u.m.AntPathRequestMatcher Checking match of request : '/logincheck'; against '/js/**'
02/06 17:04:33.645 [http-bio-8080-exec-10] DEBUG o.s.s.w.u.m.AntPathRequestMatcher Checking match of request : '/logincheck'; against '/fonts/**'
02/06 17:04:33.645 [http-bio-8080-exec-10] DEBUG o.s.security.web.FilterChainProxy /loginCheck at position 1 of 13 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
02/06 17:04:33.645 [http-bio-8080-exec-10] DEBUG o.s.security.web.FilterChainProxy /loginCheck at position 2 of 13 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
02/06 17:04:33.646 [http-bio-8080-exec-10] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository HttpSession returned null object for SPRING_SECURITY_CONTEXT
02/06 17:04:33.700 [http-bio-8080-exec-10] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@705ebc6e. A new one will be created.
02/06 17:04:33.701 [http-bio-8080-exec-10] DEBUG o.s.security.web.FilterChainProxy /loginCheck at position 3 of 13 in additional filter chain; firing Filter: 'HeaderWriterFilter'
02/06 17:04:33.701 [http-bio-8080-exec-10] DEBUG o.s.security.web.FilterChainProxy /loginCheck at position 4 of 13 in additional filter chain; firing Filter: 'CsrfFilter'
02/06 17:04:33.702 [http-bio-8080-exec-10] DEBUG o.s.security.web.csrf.CsrfFilter Invalid CSRF token found for http://localhost:8080/mongodash/loginCheck
02/06 17:04:33.703 [http-bio-8080-exec-10] DEBUG o.s.web.servlet.DispatcherServlet DispatcherServlet with name 'mongodash' processing POST request for [/mongodash/403]
02/06 17:04:33.704 [http-bio-8080-exec-10] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping Looking up handler method for path /403
02/06 17:04:33.719 [http-bio-8080-exec-10] DEBUG o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver Resolving exception from handler [null]: org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported
02/06 17:04:33.719 [http-bio-8080-exec-10] DEBUG o.s.w.s.m.a.ResponseStatusExceptionResolver Resolving exception from handler [null]: org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported
02/06 17:04:33.720 [http-bio-8080-exec-10] DEBUG o.s.w.s.m.s.DefaultHandlerExceptionResolver Resolving exception from handler [null]: org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported
02/06 17:04:33.720 [http-bio-8080-exec-10] WARN  o.s.web.servlet.PageNotFound Request method 'POST' not supported
02/06 17:04:33.721 [http-bio-8080-exec-10] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
02/06 17:04:33.721 [http-bio-8080-exec-10] DEBUG o.s.web.servlet.DispatcherServlet Null ModelAndView returned to DispatcherServlet with name 'mongodash': assuming HandlerAdapter completed request handling
02/06 17:04:33.721 [http-bio-8080-exec-10] DEBUG o.s.web.servlet.DispatcherServlet Successfully completed request
02/06 17:04:33.722 [http-bio-8080-exec-10] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
02/06 17:04:33.722 [http-bio-8080-exec-10] DEBUG o.s.s.w.c.SecurityContextPersistenceFilter SecurityContextHolder now cleared, as request processing completed

: - ? , , (js, css, img), , URL- , POST .

. TL

edit # 1: ​​ spring

edit # 2: spring

+3
1

, , , CSRF .

DEBUG o.s.security.web.csrf.CsrfFilter Invalid CSRF token found for http://localhost:8080/mongodash/loginCheck

XML, CSRF XML ( ). CSRF, Spring /403 ( , Java Config). , MVC /403 HTTP POST , .

, , /403 . , (, , , ).

-, :

CSRF POST, PUT, DELETE .. , CSRF.

: @EnableWebMvcSecurity Spring JSP Thymeleaf 2.1+ , CSRF . . CSRF , .

CSRF. , , Spring Java.

CSRF HTTP- .

, , Java . , , .

+6

All Articles