Für den Anforderungsparameter '_csrf' oder den Header 'X-CSRF-TOKEN' wurde ein ungültiges CSRF-Token 'null' gefunden.

90

Ist nach der Konfiguration von Spring Security 3.2 _csrf.tokennicht an eine Anforderung oder ein Sitzungsobjekt gebunden.

Dies ist die Federsicherheitskonfiguration:

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

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

Und es rendert das nächste HTML:

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

Das Ergebnis ist der HTTP-Status 403:

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

UPDATE Nach einigem Debuggen wird das Anforderungsobjekt in feiner Form von DelegatingFilterProxy ausgegeben, aber in der Zeile 469 von CoyoteAdapter wird request.recycle () ausgeführt. das löscht alle Attribute ...

Ich teste in Tomcat 6.0.36, 7.0.50 mit JDK 1.7.

Ich habe dieses Verhalten nicht verstanden, und es wäre möglich, wenn mich jemand in Richtung eines Anwendungsbeispielkrieges mit Spring Security 3.2 weist, der mit CSRF funktioniert.

Hugo Robayo
quelle
1
Welche Spring-Version verwenden Sie? Dasselbe funktioniert für mich (es gibt jedoch Unterschiede in spring-security.xml) mit Spring 4.0.0 RELEASE (GA), Spring Security 3.2.0 RELEASE (GA) (obwohl es in Struts 2.3.16 integriert ist. Ich habe es nicht angegeben versuchen Sie es mit Spring MVC alleine). Es schlägt jedoch fehl, wenn die Anforderung mehrteilig ist, um Dateien mit dem Status 403 hochzuladen. Ich habe Probleme, eine Lösung dafür zu finden.
Winzig
Spring 3.2.6, Spring Security 3.2.0, das CSRF-Token, wurde dem http-Anforderungsobjekt hinzugefügt. Das Sitzungsobjekt ist zusammen mit dem Anforderungsthread identisch, aber wenn es ausgeht, bis es gerendert wird, entfernt der JSP alle Attribute und nur Hinterlasse ein Attribut ... filter_applied
Hugo Robayo
@Tiny: Hast du jemals eine Lösung für das mehrteilige Problem gefunden? Ich habe genau das gleiche Problem.
Rob Johansen
1
@AlienBishop: Ja, bitte überprüfen Sie diese Antwort (es wird eine Kombination aus Feder und Federbein verwendet). Wenn Sie Spring MVC alleine haben, lesen Sie bitte diese Antwort. Es ist zu beachten, dass die Reihenfolge der Filter web.xmlentscheidend ist. MultipartFiltermuss vorher deklariert werden springSecurityFilterChain. Hoffentlich hilft das. Vielen Dank.
Winzig

Antworten:

109

Es sieht so aus, als ob der CSRF-Schutz (Cross Site Request Forgery) in Ihrer Spring-Anwendung aktiviert ist. Eigentlich ist es standardmäßig aktiviert.

Laut spring.io :

Wann sollten Sie CSRF-Schutz verwenden? Wir empfehlen, den CSRF-Schutz für alle Anfragen zu verwenden, die von normalen Benutzern von einem Browser verarbeitet werden könnten. Wenn Sie nur einen Dienst erstellen, der von Nicht-Browser-Clients verwendet wird, möchten Sie wahrscheinlich den CSRF-Schutz deaktivieren.

So deaktivieren Sie es:

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

Wenn Sie jedoch den CSRF-Schutz aktiviert lassen möchten, müssen Sie das in Ihr Formular aufnehmen csrftoken. Sie können es so machen:

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

Sie können das CSRF-Token sogar in die Aktion des Formulars aufnehmen:

<form action="./upload?${_csrf.parameterName}=${_csrf.token}" method="post" enctype="multipart/form-data">
MaVRoSCy
quelle
2
Dies sollte als Antwort akzeptiert werden, da hier nicht nur erklärt wird, was zu tun ist, sondern auch, was Sie beachten sollten, bevor Sie etwas tun, um diese Fehler zu stoppen.
Thomas Carlisle
1
Sie können auch tun.csrf().ignoringAntMatchers("/h2-console/**")
insan-e
Vermeiden Sie in der obigen Antwort, den Abfrageparameterstil zu verwenden. Wenn Sie dies tun, setzen Sie Token in der Öffentlichkeit frei.
Pramod S. Nikam
31

Sollten Sie nicht zum Anmeldeformular hinzufügen?;

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

Wie hier in der Spring-Sicherheitsdokumentation angegeben

Borjab
quelle
12

Wenn Sie sich bewerben, security="none"wird kein CSRF-Token generiert. Die Seite wird nicht durch den Sicherheitsfilter geleitet. Verwenden Sie die Rolle ANONYM.

Ich bin nicht ins Detail gegangen, aber es funktioniert für mich.

 <http auto-config="true" use-expressions="true">
   <intercept-url pattern="/login.jsp" access="hasRole('ANONYMOUS')" />
   <!-- you configuration -->
   </http>
Awanish Kumar
quelle
Ich habe security = none verwendet und bin zu Ihrer Antwort übergegangen, um dieses Problem zu lösen. Es ist großartig, dass Thymeleaf automatisch den CSRF-Token hinzufügt. Vielen Dank !
RXX
7

Versuchen Sie dies zu ändern: <csrf /> in : <csrf disabled="true"/>. Es sollte csfr deaktivieren.

Arkadiusz Gibes
quelle
7

Mit Thymeleaf können Sie hinzufügen:

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

Ich hatte früher das gleiche Problem.

Ihre Konfiguration verwendet security = "none" und kann daher _csrf nicht generieren:

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

Sie können access = "IS_AUTHENTICATED_ANONYMOUSLY" für die Seite /login.jsp festlegen, die über der obigen Konfiguration ersetzt wird:

<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>
xxg
quelle
2

Ich denke, CSRF funktioniert nur mit Frühlingsformen

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

Wechseln Sie zu form:formTag und sehen Sie, dass es funktioniert.

Saurabh Kumar
quelle
Sie müssen keine Frühlingsformen verwenden: docs.spring.io/spring-security/site/docs/3.2.7.RELEASE/…
Bart Swennenhuis
1

Bitte sehen Sie sich meine funktionierende Beispielanwendung auf Github an und vergleichen Sie sie mit Ihrer Einrichtung.

manisch
quelle
Ich werde auf Spring 3.2.6 downgraden, ich hoffe es funktioniert ohne Spring MVC.
Hugo Robayo
Ja, es sollte problemlos funktionieren, da ich die Beispielanwendung aus meiner vorhandenen Anwendung in Spring 3.1.4 erstellt habe.
Manish
ha ha ha ha ha, großartig, damit es funktioniert, nur ein Downgrade ist keine Lösung. bhaiya ji @manish
Kuldeep Singh
1

Keine der Lösungen hat bei mir funktioniert. Das einzige, was in der Frühlingsform für mich funktioniert hat, ist:

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

ERSETZT MIT:

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

(Spring 5 mit aktiviertem CSRF in Java-Konfiguration)

vancho
quelle
0

Fügen Sie in Ihrem Controller Folgendes hinzu:

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

Und auf jsp Seite hinzufügen

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