Token CSRF "null" non valido trovato nel parametro di richiesta "_csrf" o nell'intestazione "X-CSRF-TOKEN"


90

Dopo aver configurato Spring Security 3.2, _csrf.tokennon è vincolato a una richiesta oa un oggetto sessione.

Questa è la configurazione della sicurezza primaverile:

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

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

E rende il prossimo html:

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

Il risultato è lo stato HTTP 403:

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

UPDATE Dopo un po 'di debug, l'oggetto request esce in forma fine DelegatingFilterProxy, ma nella riga 469 di CoyoteAdapter esegue request.recycle (); che cancella tutti gli attributi ...

Provo in Tomcat 6.0.36, 7.0.50 con JDK 1.7.

Non ho capito questo comportamento, piuttosto che, sarebbe possibile se qualcuno mi indicasse la direzione di una guerra di esempio di applicazione con Spring Security 3.2 che funziona con CSRF.


1
Quale versione Spring usi? Questa stessa cosa funziona per me (ci sono differenze, tuttavia, in spring-security.xml) con Spring 4.0.0 RELEASE (GA), Spring Security 3.2.0 RELEASE (GA) (sebbene sia integrato con Struts 2.3.16. Non gli ho dato un prova con Spring MVC da solo). Tuttavia non riesce, quando la richiesta è multiparte per il caricamento di file con lo stato 403. Sto lottando per trovare una soluzione.
Minuscolo

Spring 3.2.6, Spring Security 3.2.0, il CSRF, il token è stato aggiunto all'oggetto richiesta http, l'oggetto sessione è lo stesso insieme al thread di richiesta, ma quando esce finché non esegue il rendering, il jsp rimuove tutti gli attributi e solo lascia un attributo ... filter_applied
Hugo Robayo

@Tiny: hai mai trovato una soluzione al problema multiparte? Sto avendo lo esatto stesso problema.
Rob Johansen

1
@ AlienBishop: Sì, controlla questa risposta (utilizza una combinazione di Spring e Struts). Se hai solo Spring MVC, dai un'occhiata a questa risposta. Va notato che l'ordine dei filtri in web.xmlè fondamentale. MultipartFilterdeve essere dichiarato prima springSecurityFilterChain. Spero che aiuti. Grazie.
Minuscolo

Risposte:


110

Sembra che la protezione CSRF (Cross Site Request Forgery) nella tua applicazione Spring sia abilitata. In realtà è abilitato di default.

Secondo spring.io :

Quando dovresti usare la protezione CSRF? La nostra raccomandazione è di utilizzare la protezione CSRF per qualsiasi richiesta che potrebbe essere elaborata da un browser da utenti normali. Se stai solo creando un servizio che viene utilizzato da client non browser, probabilmente vorrai disabilitare la protezione CSRF.

Quindi per disabilitarlo:

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

Se vuoi mantenere abilitata la protezione CSRF, devi includere nel modulo il file csrftoken. Puoi farlo in questo modo:

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

Puoi persino includere il token CSRF nell'azione del modulo:

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

2
Questa dovrebbe essere accettata come risposta perché spiega non solo cosa fare, ma anche cosa dovresti considerare prima di fare qualcosa per fermare questi errori.
Thomas Carlisle

1
Puoi anche farlo.csrf().ignoringAntMatchers("/h2-console/**")
insan-e

Nella risposta sopra evita di passare attraverso lo stile dei parametri di query. Se lo fai, esponi i gettoni in pubblico.
Pramod S. Nikam

31

Non dovresti aggiungere al modulo di accesso ?;

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

Come indicato nella documentazione sulla sicurezza qui in Spring


12

Se applichi, security="none"non verrà generato alcun token csrf. La pagina non passerà attraverso il filtro di sicurezza. Usa il ruolo ANONIMO.

Non sono entrato nei dettagli, ma per me funziona.

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

Stavo usando security = none e il passaggio alla tua risposta ha risolto questo problema. è fantastico thymeleaf aggiunge automaticamente il token csrf. Grazie !
rxx

7

Prova a cambiare questo: <csrf /> a questo: <csrf disabled="true"/>. Dovrebbe disabilitare csfr.


7

Con la foglia di timo puoi aggiungere:

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


4

Avevo lo stesso problema.

La tua configurazione usa security = "none" quindi non può generare _csrf:

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

puoi impostare access = "IS_AUTHENTICATED_ANONYMOUSLY" per la pagina /login.jsp sostituire la configurazione sopra :

<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

Si prega di vedere la mia applicazione di esempio funzionante su GitHub e confrontarla con la configurazione.


Effettuerò il downgrade alla spring 3.2.6, spero che funzioni senza spring mvc.
Hugo Robayo

Sì, dovrebbe funzionare senza problemi poiché ho creato l'applicazione di esempio dalla mia applicazione esistente che era su Spring 3.1.4.
virile

ah ah ah ah ah, fantastico, per farlo funzionare solo il downgrade non è una soluzione bhaiya ji @manish
Kuldeep Singh

1

Nessuna delle soluzioni ha funzionato da me. L'unico che ha funzionato per me in primavera è:

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

SOSTITUITO CON:

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

(Spring 5 con csrf abilitato nella configurazione java)


0

Nel tuo controller aggiungi quanto segue:

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

E sulla pagina jsp aggiungi

<form:form modelAttribute="someName" action="someURI?${_csrf.parameterName}=${_csrf.token}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.