Un jeton CSRF non valide «null» a été trouvé sur le paramètre de demande «_csrf» ou l'en-tête «X-CSRF-TOKEN»


90

Après avoir configuré Spring Security 3.2, _csrf.tokenn'est pas lié à une demande 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 il rend le prochain HTML:

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

Le résultat est un état HTTP 403:

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

UPDATE Après un certain débogage, l'objet de requête sort correctement 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, ce serait possible si quelqu'un me dirigeait vers une guerre d'exemples d'application avec Spring Security 3.2 qui fonctionne avec CSRF.


1
Quelle version de printemps utilisez-vous? Cette même chose fonctionne pour moi (il y a cependant des différences dans spring-security.xml) avec Spring 4.0.0 RELEASE (GA), Spring Security 3.2.0 RELEASE (GA) (bien qu'il soit intégré à Struts 2.3.16. Je ne lui ai pas donné de essayez avec Spring MVC seul). Il échoue cependant, lorsque la demande est en plusieurs parties pour télécharger des fichiers avec le statut 403. J'ai du mal à trouver une solution pour cela.
Minuscule

Spring 3.2.6, Spring Security 3.2.0, le CSRF, le jeton a été ajouté à l'objet de requête http, l'objet de session est le même avec le thread de requête, mais lorsqu'il sort jusqu'à ce qu'il rende le jsp supprime tous les attributs et seulement laissez un attribut ... filter_applied
Hugo Robayo

@Tiny: Avez-vous déjà trouvé une solution au problème en plusieurs parties? J'ai exactement le même problème.
Rob Johansen

1
@AlienBishop: Oui, veuillez consulter cette réponse (elle utilise une combinaison de Spring et Struts). Si vous avez Spring MVC seul, veuillez consulter cette réponse. Il convient de noter que l'ordre des filtres dans web.xmlest crucial. MultipartFilterdoit être déclaré avant springSecurityFilterChain. J'espère que cela pourra aider. Merci.
Minuscule

Réponses:


110

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 la protection CSRF pour toute demande qui pourrait être traitée par un navigateur par des utilisateurs normaux. Si vous créez uniquement un service utilisé par des clients autres que des navigateurs, vous souhaiterez 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 conserver la protection CSRF activée, vous devez inclure dans votre formulaire le fichier csrftoken. Vous pouvez le faire comme ceci:

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

2
Cela devrait être accepté comme réponse car il explique non seulement ce qu'il faut faire, mais aussi ce que vous devez considérer avant de faire quelque chose pour arrêter ces erreurs.
Thomas Carlisle

1
Vous pouvez aussi faire.csrf().ignoringAntMatchers("/h2-console/**")
insan-e le

Dans la réponse ci-dessus, évitez d'utiliser le style de paramètre de requête. Si vous faites cela, vous exposez des jetons en public.
Pramod S. Nikam

31

Ne devriez-vous pas ajouter au formulaire de connexion ?;

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

Comme l' indique le ici dans la documentation de sécurité Spring


12

Si vous postulez, security="none"aucun jeton csrf ne sera généré. La page ne passera pas par le filtre de sécurité. Utilisez le rôle ANONYME.

Je ne suis pas entré dans les détails, mais cela fonctionne pour moi.

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

J'utilisais security = none et le passage à votre réponse a résolu ce problème. c'est génial thymeleaf ajoute automatiquement le jeton csrf. Merci !
rxx

7

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


7

Avec thymeleaf vous pouvez ajouter:

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


4

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>


1

Veuillez consulter mon exemple d'application de travail sur Github et comparer avec votre configuration.


Je reviendrai au printemps 3.2.6, j'espère que cela fonctionnera sans spring mvc.
Hugo Robayo

Oui, cela devrait fonctionner sans problème car j'ai créé l'exemple d'application à partir de mon application existante qui était sur Spring 3.1.4.
manish

ha ha ha ha ha, super, pour le faire fonctionner, le déclassement n'est pas une solution bhaiya ji @manish
Kuldeep Singh

1

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

(Spring 5 avec csrf activé dans la configuration java)


0

Dans votre contrôleur, ajoutez ce qui suit:

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

Et sur la page jsp, ajoutez

<form:form modelAttribute="someName" action="someURI?${_csrf.parameterName}=${_csrf.token}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.