2016-04-20 12 views
2

私はSpring SecurityのCSRF保護について多くのことを読んでいますが、まだ少し苦労しています。ドキュメントはいつものように素晴らしいですが、サーバー上でhtmlコードをレンダリングし、すべてのフォームに隠しフィールドを追加できるという考えに完全に基づいています。今私はAngularJSとJavaScriptを使ってバックエンドを呼び出すので、これは本当にオプションではありません。SpringセキュリティRESTバックエンドのCSRFの保護 - クライアントへのシンクロナイザートークンパターンの転送

この場合、クライアントにトークンを実際に取得する最も良い方法は何ですか(Rest Backend/AngularJS frontend)? AngularJSは$ resource内にCSRFのサポートを組み込んでいるようで、トークンを取得してそれをhttpヘッダー "X-XSRF-TOKEN"として今後のリクエストで送るために "XSRF-TOKEN"というクッキーが必要です。したがって、すべてのリクエストにはhttpヘッダーとCookieが含まれます。サーバー側では、ヘッダーを読んでセッションに格納されているトークンと比較することができます。

私はこの問題を抱えていますが、それは少し複雑に思えます。ログイン自体は保護される必要があるため、CSRFトークンのためだけに一時的なセッションを作成する必要があります。これは本当に必要ですか?

これはちょっと愚かな質問ですが、なぜクライアント側でランダムトークンを作成し、それをクライアント側のHTTPヘッダーとCookieとして設定できないのでしょうか。これは "OWASP double submit cookie"と似ていますが、クライアント側でトークンを生成します。そうすれば、サーバーはログインの前にセッションを持つ必要はありません。なぜなら、2つの送信されたトークンを比較するだけかもしれないからです。攻撃者はHTTPヘッダーを送信することができましたが、同じオリジンポリシーではCookieを読み取ったり設定したりすることができず、実際には推測できない限り一致することはできませんでした。

ここでは、クライアント側で安全なトークンを生成することは危険に思えますが、私はそれを避けることができます。しかし、なぜですか?私は何かが見逃されているように感じます、SpringSecurityがトークンをセッションに格納する理由は間違いありません。

私を啓発してください:)

+0

[Spring CSRFの快適なWeb​​サービスへのアクセス方法](http://stackoverflow.com/questions/33125598/how-to-access-spring-csrf-restful-web-service)多分役に立つでしょうか? – holmis83

+0

2週間前に既に問題を解決しましたが、ここでは言及していませんでした。私は今答えを掲載しました。しかし、ありがとう! –

答えて

1

Iは、HTTPヘッダ "X-CSRF-TOKEN"(名前は設定可能です)からCSRFトークンを読み取り、上のHTTPヘッダとして送信spring-security-csrf-token-interceptor-extendedを、使用して終了さらなるリクエスト。

私が唯一必要だったのは、Spring SecurityがトークンをHTTPヘッダーとして送信することでした(サーバー側でHTMLコードをレンダリングしないため、非表示フィールドとして追加できません)。

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

フィルタは、基本的に正常CSRF_FILTER後に実行され、 "_csrf" 要求属性を読み出す(CSRF_FILTERによってそこに置かれている)とヘッダとして設定する "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); 
    } 
} 
関連する問題