Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'
Asked Answered
S

11

96

After configuring Spring Security 3.2, _csrf.token is not bound to a request or a session object.

This is the spring security config:

<http pattern="/login.jsp" security="none"/>

<http>
    <intercept-url pattern="/**" access="ROLE_USER"/>
    <form-login login-page="/login.jsp"
                authentication-failure-url="/login.jsp?error=1"
                default-target-url="/index.jsp"/>
    <logout/>
    <csrf />
</http>

<authentication-manager>
    <authentication-provider>
        <user-service>
            <user name="test" password="test" authorities="ROLE_USER/>
        </user-service>
    </authentication-provider>
</authentication-manager>

The login.jsp file

<form name="f" action="${contextPath}/j_spring_security_check" method="post" >
    <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
    <button id="ingresarButton"
            name="submit"
            type="submit"
            class="right"
            style="margin-right: 10px;">Ingresar</button>
    <span>
        <label for="usuario">Usuario :</label>
        <input type="text" name="j_username" id="u" class="" value=''/>
    </span>
    <span>
        <label for="clave">Contrase&ntilde;a :</label>

        <input type="password"
               name="j_password"
               id="p"
               class=""
               onfocus="vc_psfocus = 1;"
               value="">
    </span>
</form>

And it renders the next html:

<input type="hidden" name="" value="" />

The result is 403 HTTP status:

Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.

UPDATE After some debug, the request object gets out fine form DelegatingFilterProxy, but in the line 469 of CoyoteAdapter it executes request.recycle(); that erases all the attributes...

I test in Tomcat 6.0.36, 7.0.50 with JDK 1.7.

I have not understood this behavior, rather than, it would be possible if someone point me in the direction of some application sample war with Spring Security 3.2 that works with CSRF.

Stay answered 15/1, 2014 at 2:27 Comment(4)
What Spring version do you use? This same thing works for me (there are differences however, in spring-security.xml) with Spring 4.0.0 RELEASE (GA), Spring Security 3.2.0 RELEASE (GA) (though it is integrated with Struts 2.3.16. I did not give it a try with Spring MVC alone). It however fails, when the request is multipart for uploading files with the status 403. I'm struggling to find a solution for it.Polonaise
Spring 3.2.6, Spring Security 3.2.0, the CSRF, token was added to the http-request object, the session object is the same along with the request thread, but when go out until its renders the jsp remove all attributes and only leave an attribute ...filter_appliedStay
@Tiny: Did you ever find a solution to the multipart problem? I'm having the exact same issue.Outboard
@AlienBishop : Yes, please check out this answer (it uses a combination of Spring and Struts). If you have Spring MVC alone then, please check out this answer. It should be noted that the order of filters in web.xml is crucial. MultipartFilter must be declared before springSecurityFilterChain. Hope that helps. Thanks.Polonaise
W
116

It looks like the CSRF (Cross Site Request Forgery) protection in your Spring application is enabled. Actually it is enabled by default.

According to spring.io:

When should you use CSRF protection? Our recommendation is to use CSRF protection for any request that could be processed by a browser by normal users. If you are only creating a service that is used by non-browser clients, you will likely want to disable CSRF protection.

So to disable it:

@Configuration
public class RestSecurityConfig extends WebSecurityConfigurerAdapter {
  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable();
  }
}

If you want though to keep CSRF protection enabled then you have to include in your form the csrftoken. You can do it like this:

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

You can even include the CSRF token in the form's action:

<form action="./upload?${_csrf.parameterName}=${_csrf.token}" method="post" enctype="multipart/form-data">
Whitesmith answered 28/4, 2015 at 11:16 Comment(4)
This should be accepted as the answer because it explains not only what to do, but also what you should consider before doing something to stop these errors.Peddling
You can also do .csrf().ignoringAntMatchers("/h2-console/**")Lipocaic
In above answer avoid going via query parameter style. If you do this you are exposing tokens in public.Penicillate
Question, i did use .csrf().disable() but I still get the null token error, how is that possible? It's been driving me mad for the past weekPersonalism
C
32

Shouldn't you add to the login form?;

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

As stated in the here in the Spring security documentation

Cryobiology answered 6/6, 2014 at 15:50 Comment(0)
B
12

If you will apply security="none" then no csrf token will be generated. The page will not pass through security filter. Use role ANONYMOUS.

I have not gone in details, but it is working for me.

 <http auto-config="true" use-expressions="true">
   <intercept-url pattern="/login.jsp" access="hasRole('ANONYMOUS')" />
   <!-- you configuration -->
   </http>
Behre answered 9/8, 2015 at 6:9 Comment(1)
I was using security=none and moving to your answer solved this issue. it is awesome thymeleaf automatically adds the csrf token. Thanks !Tartuffery
C
7

Try to change this: <csrf /> to this : <csrf disabled="true"/>. It should disable csfr.

Collocutor answered 9/5, 2015 at 21:20 Comment(0)
C
7

With thymeleaf you may add:

<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>
Cobbs answered 17/10, 2016 at 17:5 Comment(0)
E
6

Spring documentation to disable csrf: https://docs.spring.io/spring-security/site/docs/current/reference/html/csrf.html#csrf-configure

@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {

   @Override
   protected void configure(HttpSecurity http) throws Exception {
      http.csrf().disable();
   }
}
Electrobiology answered 13/1, 2017 at 7:12 Comment(1)
Don't copy existing answers, please.Kariekaril
M
4

I used to have the same problem.

Your config use security="none" so cannot generate _csrf:

<http pattern="/login.jsp" security="none"/>

you can set access="IS_AUTHENTICATED_ANONYMOUSLY" for page /login.jsp replace above config:

<http>
    <intercept-url pattern="/login.jsp*" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
    <intercept-url pattern="/**" access="ROLE_USER"/>
    <form-login login-page="/login.jsp"
            authentication-failure-url="/login.jsp?error=1"
            default-target-url="/index.jsp"/>
    <logout/>
    <csrf />
</http>
Minnesinger answered 2/9, 2015 at 8:7 Comment(0)
S
2

i think csrf only works with spring forms

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>

change to form:form tag and see it that works.

Sylvanite answered 14/6, 2014 at 7:38 Comment(1)
You dont need to use spring forms: docs.spring.io/spring-security/site/docs/3.2.7.RELEASE/…Sousaphone
C
1

Please see my working sample application on Github and compare with your set up.

Centroid answered 10/2, 2014 at 3:26 Comment(3)
I will downgrade to spring 3.2.6, I hope it works without spring mvc.Stay
Yes, it should work without problems as I created the sample application out of my existing application that was on Spring 3.1.4.Centroid
ha ha ha ha ha, great, to make it working just downgrading is not solution bhaiya ji @CentroidEduce
M
1

Neither one of the solutions worked form me. The only one that worked for me in Spring form is:

action="./upload?${_csrf.parameterName}=${_csrf.token}"

REPLACED WITH:

action="./upload?_csrf=${_csrf.token}"

(Spring 5 with enabled csrf in java configuration)

Malynda answered 21/2, 2018 at 12:33 Comment(0)
S
0

In your controller add the following:

@RequestParam(value = "_csrf", required = false) String csrf

And on jsp page add

<form:form modelAttribute="someName" action="someURI?${_csrf.parameterName}=${_csrf.token}
Signesignet answered 31/7, 2017 at 22:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.