Spring Rest Service - Invalid CSRF token when I at

2019-02-13 13:52发布

问题:

I have a Spring MVC REST service, with Spring Security (3.2.5.RELEASE) enabled. When I turn on @EnableWebMvcSecurity, a login form is automatically generated for me at http://localhost:8080/login. If I use this form to login, everything works just fine.

The problem occurs when I attempt to login by sending a POST request directly. In my post request, I provide the username and password. I also include the http header 'X-CSRF-TOKEN' and for the header value, I use the JSESSIONID that I see has been generated in a cookie. But when I send this POST request, I get back the following result:

HTTP Status 403 - Invalid CSRF Token '29F5E49EFE8D758D4903C0491D56433E' 
was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.

What am I doing wrong? Am I providing the wrong token value? What is this JSESSIONID? If I don't enter a value for this header, or omit the header all together, it tells me "Null CSRF token found".

Below is my Spring Security configuration:

@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
            .withUser("user").password("password").roles("USER");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/secure/**").authenticated()
                .and()
            .formLogin()
                .usernameParameter("username")
                .passwordParameter("password")        
                .and()
            .logout()
                .and()
            .httpBasic()
                .and()
            .csrf(); 
    }
}

I'd really appreciate any help! Thanks in advance!

回答1:

(1) Include the CSRF token within all your AJAX requests.

$(function () {
    var token = $('#logoutform>input').val();
    var header = $('#logoutform>input').attr('name');
    $(document).ajaxSend(function(e, xhr, options) {
        xhr.setRequestHeader('X-CSRF-TOKEN', token);
    });
 });

(2) Simple request .

<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>


回答2:

You need to send the csrf token when you submit the login form. Please add the below line in the HTML form:

<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>


回答3:

you need <meta name="_csrf" content="${_csrf.token}"/> , https://spring.io/blog/2013/08/21/spring-security-3-2-0-rc1-highlights-csrf-protection/#ajax-requests

or if you are using thymeleaf <meta name="_csrf" th:content="${_csrf.token}" />