Spring MVCとSpring Securityによるサーブレット3の非同期サポート

Spring MVCおよびSpring Securityによるサーブレット3非同期サポート

1. 前書き

このクイックチュートリアルでは、the Servlet 3 support for async requests, and how Spring MVC and Spring Security handle theseに焦点を当てます。

Webアプリケーションの非同期性の最も基本的な動機は、長時間実行されるリクエストを処理することです。 ほとんどのユースケースでは、SpringSecurityプリンシパルがこれらのスレッドに伝達されていることを確認する必要があります。

そしてもちろん、Spring Securityintegrates with @AsyncはMVCの範囲外であり、HTTPリクエストも処理します。

2. Mavenの依存関係

Spring MVCで非同期統合を使用するには、次の依存関係をpom.xmlに含める必要があります。


    org.springframework.security
    spring-security-web
    4.2.1.RELEASE


    org.springframework.security
    spring-security-config
    4.2.1.RELEASE

Spring Securityの依存関係の最新バージョンはhereにあります。

3. Spring MVCと@Async

公式のdocsによると、Spring SecurityはWebAsyncManagerと統合されています。

最初のステップは、非同期リクエストを処理するためにspringSecurityFilterChainが設定されていることを確認することです。 Servlet構成クラスに次の行を追加することにより、Java構成でそれを行うことができます。

dispatcher.setAsyncSupported(true);

またはXML設定で:


    springSecurityFilterChain
    org.springframework.web.filter.DelegatingFilterProxy
    true


    springSecurityFilterChain
    /*
    REQUEST
    ASYNC

また、サーブレット構成でasync-supportedパラメータを有効にする必要があります。


    ...
    true
    ...

これで、SecurityContextが伝播された非同期リクエストを送信する準備が整いました。

Spring Securityの内部メカニズムにより、応答が別のThreadでコミットされ、ユーザーがログアウトしたときに、SecurityContextがクリアされなくなります。

4. ユースケース

簡単な例でこれを実際に見てみましょう。

@Override
public Callable checkIfPrincipalPropagated() {
    Object before
      = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    log.info("Before new thread: " + before);

    return new Callable() {
        public Boolean call() throws Exception {
            Object after
              = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
            log.info("New thread: " + after);
            return before == after;
        }
    };
}

SpringSecurityContextが新しいスレッドに伝播されているかどうかを確認したいと思います。

上記のメソッドでは、ログに表示されるように、SecurityContextが含まれた状態でCallableが自動的に実行されます。

web - 2017-01-02 10:42:19,011 [http-nio-8081-exec-3] INFO
  o.example.web.service.AsyncService - Before new thread:
  [email protected]:
  Username: temporary; Password: [PROTECTED]; Enabled: true;
  AccountNonExpired: true; credentialsNonExpired: true;
  AccountNonLocked: true; Granted Authorities: ROLE_ADMIN

web - 2017-01-02 10:42:19,020 [MvcAsync1] INFO
  o.example.web.service.AsyncService - New thread:
  [email protected]:
  Username: temporary; Password: [PROTECTED]; Enabled: true;
  AccountNonExpired: true; credentialsNonExpired: true;
  AccountNonLocked: true; Granted Authorities: ROLE_ADMIN

伝播するSecurityContextを設定しないと、2番目の要求はnull値になります。

伝播されたSecurityContextで非同期リクエストを使用する他の重要なユースケースもあります。

  • 並列に実行でき、実行にかなりの時間がかかる可能性がある複数の外部リクエストを作成したい

  • ローカルで行う重要な処理がいくつかあり、外部リクエストはそれと並行して実行できます

  • その他は、たとえばメールを送信するなど、忘れがたいシナリオを表します

複数のメソッド呼び出しが以前に同期方式でチェーンされていた場合、これらを非同期アプローチに変換するには結果を同期する必要があることに注意してください。

5. 結論

この短いチュートリアルでは、認証されたコンテキストで非同期リクエストを処理するためのSpringサポートを説明しました.

プログラミングモデルの観点から見ると、新しい機能は一見シンプルに見えます。 しかし、より深い理解を必要とするいくつかの側面が確かにあります。

この例は、Mavenプロジェクトover on Githubとしても利用できます。