2017-09-09 4 views
0

Ich habe versucht, CSRF/XSRF-Schutz zu meiner Anwendung hinzufügen, aber lief in seltsames Verhalten. Alle bekommen Anfragen funktionieren gut, aber auf alle Post/put/delete Ich bekomme 403 nicht autorisiert. Und das Seltsamste ist, dass, wenn ich versucht habe, meinen CSRF-Filter zu debuggen, Anfragen ihn nicht erreichen, sie werden irgendwo früher zurückgewiesen. Sie erreichen nicht einmal meinen Authentifizierungsfilter, so dass ich nicht herausfinden kann, was das Problem sein könnte.CSRF/XSRF-Schutz für Spring Security und AngularJS

Meine Sicherheit config:

 @Override 
     public void configure(HttpSecurity http) throws Exception { 
      http 
        ... 
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) 
        .and() 
        .addFilterBefore(new StatelessAuthenticationFilter(tokenAuthenticationService()), UsernamePasswordAuthenticationFilter.class) 
        .addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class) 
        .csrf().csrfTokenRepository(csrfTokenRepository()); 
     } 

     private CsrfTokenRepository csrfTokenRepository() { 
      HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository(); 
      repository.setHeaderName("X-XSRF-TOKEN"); 
      return repository; 
     } 

ich nicht hinzufügen, die Filter, da wie gesagt, die Anforderungen sie nicht erreichen. Aber wenn nötig, werde ich meine Frage vervollständigen. Ich hoffe auf Ihre Hilfe, danke im Voraus!

Antwort

0

Vielen Dank für die Antworten, sie haben mir wirklich geholfen, eine Lösung zu finden. Und ich möchte meine Lösung teilen, wenn in Zukunft jemand mit dem gleichen Problem konfrontiert wird.

Wie bereits in den Antworten, die ich SessionCreationPolicy.STATELESS verwendet und hatte keine Sitzungen so statt HttpSessionCsrfTokenRepository Ich hatte CookieCsrfTokenRepository mit withHttpOnlyFalse() zu verwenden AngularJS zu erlauben, Cookies zu lesen.

Als Ergebnis habe ich eine Konfiguration wie folgt aus:

@Override 
public void configure(HttpSecurity http) throws Exception { 
    http 
      ... 
      .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) 
      .and() 
      .addFilterBefore(new StatelessAuthenticationFilter(tokenAuthenticationService()), UsernamePasswordAuthenticationFilter.class) 
      .addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class) 
      .csrf().csrfTokenRepository(csrfTokenRepository()); 
} 

Wenn jemand daran interessiert, wie die CsrfHeaderFilter aussieht:

public class CsrfHeaderFilter extends OncePerRequestFilter { 

    @Override 
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) 
      throws ServletException, IOException { 
     CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName()); 
     if (csrf != null) { 
      Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN"); 
      String token = csrf.getToken(); 
      if (cookie==null || token!=null && !token.equals(cookie.getValue())) { 
       cookie = new Cookie("XSRF-TOKEN", token); 
       cookie.setPath("/"); 
       response.addCookie(cookie); 
      } 
     } 
     filterChain.doFilter(request, response); 
    } 
} 

Mein zweites Problem CORS war. AngularJS Dokumentation sagt:

"Der Header wird nicht für domänenübergreifende Anfragen festgelegt."

Um dieses Problem zu lösen, hatte ich einen HTTP Interceptor zu verwenden:.

.factory('XsrfInterceptor', function ($cookies) { 
    return { 
    request: function (config) { 
     var headerName = 'X-XSRF-TOKEN'; 
     var cookieName = 'XSRF-TOKEN'; 
     config.headers[headerName] = $cookies.get(cookieName); 
     return config; 
    } 
    }; 
}); 

.config(['$httpProvider', function($httpProvider) { 
    $httpProvider.interceptors.push('XsrfInterceptor'); 
}]); 

ich meine Antwort hoffe, nützlich sein wird

0

Angenommen, dass der Rest Ihrer config/filters ordnungsgemäß funktioniert, stehen Sie vor diesem Problem: SessionCreationPolicy.STATELESS.

Sie können einen Blick unter die Haube von Spring CsrfFilter werfen. Sie werden sehen, dass der Wert jedes CSRF-Tokens für jeden Benutzer innerhalb einer Sitzung gespeichert werden muss, und da Sie keine Sitzungen verwenden, kann dies nicht durchgeführt werden.

Was als nächstes zu tun ist - liegt ganz bei Ihnen. Einige Leute sagen, dass, wenn Sie App staatenlos ist, eigentlich kein CSRF-Schutz benötigt wird. Spring docs sagen, dass CSRF-Angriffe immer noch relevant sind. Ich denke, es hängt wirklich von Ihrem Authentifizierungsmechanismus ab.

Sie können auch zum Beispiel this nice article betrachten.

Ich hoffe, es hilft.

+0

aus diesem Grunde ich meine benutzerdefinierten CSRF-Filter implementiert, aber mein Das Problem ist, dass Anfragen es nicht einmal erreichen. "Was ist sehr seltsam. –

+0

@AnarSultanov, können Sie bitte den Code von Ihnen Filter? Obwohl, ist es egal, weil Sie Filter hinzufügen * nach * Spring' CsrfFilter'. Und wenn der Springs-Filter das Token der Benutzersitzung nicht finden kann (was nicht erreicht werden kann, weil es keine Sitzung gibt) ruft 'accessDeniedHandler' auf und macht' return' (breaking filters chain), was bedeutet, dass es filterChain.doFilter (request, response); 'nicht aufruft, damit Ihr Filter nicht wirklich danach aufgerufen werden kann. Wenn Sie Ihren eigenen CSRF-Schutz implementieren, dann sollten Sie die Implementierung von Spring deaktivieren, indem Sie '.csrf(). Disable()' aufrufen. – Leffchik

+0

Ich habe gefunden, was mein Problem sein kann. Ich habe XSRF-TOKEN in Cookies, aber eckig hinzufügen Header mit diesem Token nicht Anfragen. Jetzt versuche ich herauszufinden, warum und wie ich das beheben kann. –

0

Im Prinzip speichert der CSRF-Mechanismus in Spring das CSRF-Token in einem Nur-HTTP-Cookie. Da JavaScript nicht nur HTTP-Cookie zugreifen können, müssen Sie Feder sagen, HTTP deaktivieren nur:

.and().csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()); 

Dann können Sie das Cookie von Angular lesen und an die mit jeder Anforderung XSRF-Token-Header hinzufügen.

Dies ist der allgemeine Fall. Ich bin mir nicht sicher, ob dies zu Ihrem Spezialfall passt.

Verwandte Themen