Spring MVCとSpring Securityによるサーブレット3の非同期サポート
1前書き
このクイックチュートリアルでは、非同期要求に対するServlet 3のサポート、およびSpring MVCとSpring Securityがこれらをどのように処理するかに焦点を当てます** 。
Webアプリケーションの非同期性の最も基本的な動機は、長時間実行される要求を処理することです。ほとんどのユースケースでは、Spring Securityプリンシパルが確実にこれらのスレッドに伝播されるようにする必要があります。
そしてもちろん、Spring Securityリンク:/spring-security-async-principal-propagation[MVCの範囲外で
@ Async
と統合し、HTTPリクエストを処理する]。
2 Mavenの依存関係
Spring MVCで非同期統合を使用するためには、__pom.xmlに以下の依存関係を含める必要があります。
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>4.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>4.2.1.RELEASE</version>
</dependency>
Spring Securityの依存関係の最新版はhttps://search.maven.org/classic/#search%7Cga%7C1%7Cg%3A%22org.springframework.security%22[here]にあります。
3 Spring MVCと
@ Async
docs
によると、Spring Security __http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/web/context/request/async/WebAsyncManager.htmlに統合
最初のステップは、
springSecurityFilterChain
が非同期要求を処理するように設定されていることを確認することです。
Servlet
configクラスに次の行を追加することで、Java configでそれを行うことができます。
dispatcher.setAsyncSupported(true);
またはXML設定では:
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<async-supported>true</async-supported>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/** </url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>ASYNC</dispatcher>
</filter-mapping>
また、サーブレット設定で
async-supported
パラメータを有効にする必要があります。
<servlet>
...
<async-supported>true</async-supported>
...
</servlet>
これで、
SecurityContext
を伝播して非同期要求を送信する準備が整いました。
Spring Securityの内部メカニズムにより、応答が別の
Thread
でコミットされてユーザーがログアウトしたときに、
SecurityContext
がクリアされなくなります。
4ユースケース
簡単な例でこれを実際に見てみましょう。
@Override
public Callable<Boolean> checkIfPrincipalPropagated() {
Object before
= SecurityContextHolder.getContext().getAuthentication().getPrincipal();
log.info("Before new thread: " + before);
return new Callable<Boolean>() {
public Boolean call() throws Exception {
Object after
= SecurityContextHolder.getContext().getAuthentication().getPrincipal();
log.info("New thread: " + after);
return before == after;
}
};
}
Springの
SecurityContext
が新しいスレッドに伝播されているかどうかをチェックしたい
上記のメソッドは自動的に
Callable
を
SecurityContext
を含めて実行します。
web - 2017-01-02 10:42:19,011[http-nio-8081-exec-3]INFO
o.baeldung.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.baeldung.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
valueになります。
伝播された
SecurityContext
で非同期リクエストを使用する他の重要なユースケースもあります。
-
並行して実行できる複数の外部リクエストを作成したい
実行にかなりの時間がかかる場合があります
** 私たちはローカルでそして私たちの外部でやるべきいくつかの重要な処理を持って
リクエストはそれと並行して実行できます。
** otherは、例えば送信するなどの、忘れ去りシナリオを表します
Eメール
私たちの複数のメソッド呼び出しが以前は同期的にチェーンされていた場合、これらを非同期のアプローチに変換するには結果を同期させる必要があるかもしれません。
5結論
この短いチュートリアルでは、認証されたコンテキストで非同期リクエストを処理するためのSpringサポートを説明しました
プログラミングモデルの観点からすると、新しい機能は一見シンプルに見えます。しかし、もっと深い理解を必要とするいくつかの側面が確かにあります。
この例はMavenプロジェクトhttps://github.com/eugenp/tutorials/tree/master/spring-security-rest[over on Github]としても利用可能です。