web-dev-qa-db-fra.com

Le jeton CSRF 'null' non valide a été trouvé dans le paramètre de requête '_csrf' ou dans l'en-tête 'X-CSRF-TOKEN'

Après avoir configuré Spring Security 3.2, _csrf.token n'est pas lié à une requête ou à un objet de session.

Voici la configuration de sécurité du printemps:

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

Le fichier login.jsp

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

Et cela rend le prochain html:

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

Le résultat est le statut HTTP 403:

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

UPDATE Après un débogage, l'objet de requête sort sous forme fine de DelegatingFilterProxy, mais dans la ligne 469 de CoyoteAdapter, il exécute request.recycle (); qui efface tous les attributs ...

Je teste dans Tomcat 6.0.36, 7.0.50 avec JDK 1.7.

Je n'ai pas compris ce comportement, plutôt que de le faire si quelqu'un me dirigeait vers un exemple d'application de guerre avec Spring Security 3.2 qui fonctionne avec CSRF.

81
Hugo Robayo

Il semble que la protection CSRF (Cross Site Request Forgery) de votre application Spring soit activée. En fait, il est activé par défaut. 

Selon spring.io :

Quand devriez-vous utiliser la protection CSRF? Notre recommandation est d'utiliser CSRF protection pour toute demande pouvant être traitée par un navigateur par utilisateurs normaux. Si vous créez uniquement un service utilisé par sans navigateur, vous voudrez probablement désactiver la protection CSRF.

Donc pour le désactiver:

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

Si vous souhaitez toutefois conserver la protection CSRF activée, vous devez inclure dans votre formulaire la variable csrftoken. Vous pouvez le faire comme ça:

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

Vous pouvez même inclure le jeton CSRF dans l'action du formulaire:

<form action="./upload?${_csrf.parameterName}=${_csrf.token}" method="post" enctype="multipart/form-data">
85
MaVRoSCy

Ne devriez-vous pas ajouter au formulaire de connexion?

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

Comme indiqué dans la ici dans la documentation de sécurité de Spring

28
borjab

si vous appliquez security = "none", aucun jeton csrf ne sera généré. page ne passera pas par le filtre de sécurité. Utilisez le rôle ANONYMOUS.

Je ne suis pas allé dans les détails, mais ça marche pour moi.

 <http auto-config="true" use-expressions="true">
   <intercept-url pattern="/login.jsp" access="hasRole('ANONYMOUS')" />
   <!-- you configuration -->
   </http>
12
Awanish Kumar

Documentation Spring pour désactiver 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();
   }
}
6
Rahul Raj

Avec thymeleaf, vous pouvez ajouter:

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

Essayez de changer ceci: <csrf /> en ceci: <csrf disabled="true"/>. Cela devrait désactiver csfr.

6
Arkadiusz Gibes

J'ai déjà eu le même problème.

Votre configuration utilise security = "none" et ne peut donc pas générer _csrf:

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

vous pouvez définir access = "IS_AUTHENTICATED_ANONYMOUSLY" pour la page /login.jsp remplacer la configuration ci-dessus:

<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>
4
xxg

je pense que CSRF ne fonctionne qu'avec des formes de printemps

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

passez à la balise form:form et voyez ce qui fonctionne.

2
Saurabh Kumar

S'il vous plaît voir mon exemple d'application de travail sur Github et comparer avec votre configuration.

1
manish

Aucune des solutions n'a fonctionné de moi. Le seul qui a fonctionné pour moi sous forme de printemps est:

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

REMPLACÉ PAR:

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

(Printemps 5 avec csrf activé dans la configuration Java)

1
vancho

Dans votre contrôleur, ajoutez ce qui suit:

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

Et sur la page jsp ajouter

<form:form modelAttribute="someName" action="someURI?${_csrf.parameterName}=${_csrf.token}
0
Taras Melnyk