2016-04-20 17 views
2

Ich lese viel über CSRF-Schutz von Spring Security, aber ich habe immer noch ein wenig zu kämpfen. Jetzt ist die Dokumentation wie immer großartig, aber sie basiert vollständig auf der Idee, dass Sie HTML-Code auf dem Server rendern und jedem Formular ein verstecktes Feld hinzufügen können. Jetzt, da ich AngularJS und JavaScript benutze, um das Backend aufzurufen, ist dies nicht wirklich eine Option.Spring Security CSRF-Schutz von REST-Backend - Übertragung von Synchronizer Token Pattern an den Client

Also, was ist der beste Weg, um das Token in diesem Fall tatsächlich zum Client zu bekommen (Rest Backend/AngularJS Frontend)? AngularJS scheint Unterstützung für CSRF in $ resource eingebaut zu haben und erwartet ein Cookie namens "XSRF-TOKEN", um das Token abzurufen und es als HTTP-Header "X-XSRF-TOKEN" in weiteren Anfragen zu senden. Jede Anfrage enthält also sowohl den HTTP-Header als auch den Cookie. Jetzt auf Serverseite konnte ich die Überschrift lesen und sie mit dem Token vergleichen, das ich in der Sitzung speicherte.

Das Problem habe ich damit, dass es ein bisschen kompliziert erscheint. Da die Anmeldung selbst geschützt werden muss, muss nur für das CSRF-Token eine temporäre Sitzung erstellt werden. Ist das wirklich notwendig?

Vielleicht ist das nur eine dumme Frage, aber warum kann ich nicht einfach ein zufälliges Token auf der Client-Seite erstellen und es als HTTP-Header und Cookie auf der Client-Seite festlegen. Dies würde "OWASP double submit cookie" ähneln, aber das Token auf der Client-Seite generieren. Auf diese Weise würde der Server vor dem Login keine Sitzung benötigen, da er nur die zwei übergebenen Tokens vergleichen könnte. Während der Angreifer den HTTP-Header senden konnte, hatte er keine Möglichkeit, den Cookie zu lesen oder zu setzen und konnte keine Übereinstimmung finden, solange die Nummer praktisch nicht zu ermitteln ist.

Jetzt instinktiv generieren eine sichere Token auf Client-Seite scheint gefährlich für mich, und ich denke, ich konnte es vermeiden .. aber WARUM? Ich habe das Gefühl, dass ich etwas vermisst habe, und es gibt einen guten Grund, warum SpringSecurity das Token in der Sitzung speichert, oder?

Bitte erleuchte mich :)

+0

[Wie Zugang zu Spring CSRF erholsamen Web-Service] (http://stackoverflow.com/questions/33125598/how-to-access-spring-csrf-restful-web-service) vielleicht hilfreich? – holmis83

+0

Ich habe das Problem bereits vor 2 Wochen gelöst, aber vergessen, es hier zu erwähnen. Ich habe die Antwort jetzt gepostet. Trotzdem danke! –

Antwort

1

ich landete mit spring-security-csrf-token-interceptor-extended, die die CSRF-Token aus der http-Header "X-CSRF-token" liest (Name ist konfigurierbar) und sendet sie als http-Header auf weitere Anfragen

Nun musste ich Spring-Security nur noch dazu bringen, den Token als HTTP-Header zu senden (da ich HTML-Code nicht serverseitig rendere und daher nicht als verstecktes Feld hinzufügen kann).

<security:http .... 
    <security:custom-filter ref="csrfTokenResponseHeaderBindingFilter" after="CSRF_FILTER"/> 
.... 
</security:http> 

Der Filter läuft im Prinzip nach dem normalen CSRF_FILTER und liest die "_csrf" request-Attribut (welches durch CSRF_FILTER gesetzt wird) und setzt sie als Kopfzeile "X-CSRF-TOKEN"

public class CsrfTokenResponseHeaderBindingFilter extends OncePerRequestFilter { 
    protected static final String REQUEST_ATTRIBUTE_NAME = "_csrf"; 
    protected static final String RESPONSE_TOKEN_NAME = "X-CSRF-TOKEN"; 

    @Override 
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, javax.servlet.FilterChain filterChain) throws ServletException, IOException { 
     CsrfToken token = (CsrfToken) request.getAttribute(REQUEST_ATTRIBUTE_NAME); 

     if (token != null) { 
      response.setHeader(RESPONSE_TOKEN_NAME, token.getToken()); 
     } 

     filterChain.doFilter(request, response); 
    } 
}