SlideShare ist ein Scribd-Unternehmen logo
1 von 22
Downloaden Sie, um offline zu lesen
1
今こそ知りたいSpring Security
2020/12/17
日本Springユーザ会
土岐 孝平
自己紹介
• 土岐 孝平
• 合同会社 現場指向
• Webアプリ「メモラキー」の運営
• システム開発の支援
• 研修の講師
• 書籍の執筆
2
[改訂新版]Spring入門https://www.memorarchy.com
想定する聴講者
• なんとなく使ってはいるが、裏で何が起こってるのか
わからず、もやもやしている
• 少し触ったけど、難しそうなので自前にしようか悩ん
でいる
3
Spring Securityに触ったことがある方が前提です
本セッションの目的
• Spring Securityが裏で何をやっているかを知って、
問題が起きたときのデバッグや、カスタマイズ方法
の調査を円滑にする
• キーとなる以下の2つを抑える
– Security Filter Chain
– Security Context
4
網羅的な機能の説明や、設定ノウハウの説明は行いません
Security Filter Chainとは?
• Spring Securityが提供するFilter※の繋がり
• Servlet Filterの仕組みを使って処理を挟み込む
• 各Filterは、認証、URLパスの認可、CSRF防止などの役割
を持つ
5
※ 個々のFilterは
ServletのFilterイン
タフェースを実装し
ているが、Servletコ
ンテナに登録されて
いる訳ではない
Filter1
FilterX
DispatcherServlet
Delegating
FilterProxy
ブラウザ
・・
・
・・・
Controller
・・
・
ServletのFilter Chain
★Security Filter
Chain
Filter2
Spring MVCのサーブ
レット
主なFilter
6
クラス名 役割
CsrfFilter CSRFトークンの発行やチェックを行う
HeaderWriterFilter セキュリティ関連のレスポンスヘッダを
設定する
BasicAuthenticationFilter Basic認証を行う
UsernamePasswordAuthenticationFilter フォーム認証を行う
ExceptionTranslationFilter 後続の処理で発生した認証・認可の例
外をキャッチしてハンドリング(エラー画
面に遷移など)する
FilterSecurityInterceptor URLのパスの認可を行う
SecurityContextPersistenceFilter 「Security Context」を用意して、HTTP
セッションやThreadLocalに格納する
次ページで説明
Security Context
• 認証したユーザ情報(IDや権限など)を格納するオブジェクト
• HTTPセッションに保持されるため、リクエストを跨ってユー
ザ情報を参照できる
• ThreadLocal(スレッド毎にデータを管理してくれる)にも保持
されるため、リクエスト(スレッド)の処理内の任意のタイミング
でユーザ情報を参照可能
– Controllerの引数で受けとる
– 画面にユーザ情報を表示するときに参照
– staticメソッドでプログラムの任意の箇所で参照
• SecurityContextHolder.getContext()
– 認可時(URLのパス、メソッド、画面内の表示非表示)に参照
7
ThreadLocal
ThreadLocalとSecurity Contextのイメージ
8
Aさん
Bさん
Bさんの
スレッド
Bさんの
Security Context
Aさんのリクエスト(スレッド)の処理
Bさんのリクエスト(スレッド)の処理
Aさんの
スレッド
Aさんの
Security Context
Security Filter Chainの作成
• WebSecurityConfigurerAdapter を継承して
@EnableWebSecurityを付けたJavaConfigのクラス
(@Configurationを付けたクラス)を作成する
• @EnableWebSecurityがインポートしている
WebSecurityConfigurationクラスの中で、Security Filter
Chainのオブジェクトが作成される
• 標準的なFilterが自動で登録されるので、メソッドをオーバー
ライドして個別の設定を行う 9
@Configuration@Configuration
@EnableWebSecurity
public class SampleSecurityConfig extends WebSecurityConfigurerAdapter {
}
個別の設定のサンプル
10
@Configuration
@EnableWebSecurity
public class SampleSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.mvcMatchers("/admin/**").hasAuthority("ADMIN")
.anyRequest().authenticated().and()
.httpBasic();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
PasswordEncoder encoder
= PasswordEncoderFactories.createDelegatingPasswordEncoder();
auth
.inMemoryAuthentication()
.withUser("foo").password(encoder.encode("passfoo")).authorities("ADMIN").and()
.withUser("bar").password(encoder.encode("passbar")).authorities("USER");
}
}
「/admin」 で始まるパスは「ADMIN」権限が
必要、それ以外は認証されてればOK
Basic認証を有効にする
「foo」ユーザは「ADMIN」権限、「bar」ユーザは
「USER」権限という認証情報をメモリ上に保管
出来上がった主なオブジェクト
11
Authentication
Manager
UserDetailsService
AccessDecision
Manager
Dispatcher
Servlet
Delegating
FilterProxy
ブラウザ
・・
・
・・
・
Controller
ServletのFilter Chain
★Security Filter Chain
ID・パスワードのチェックを
行う。認証情報は
UserDetailsServieから取得
権限のチェックを行う
認証情報を取得。今回はメ
モリ上から取得
URLのパスの認可を行う
BasicAuthenticationFilter
ExceptionTranslationFilter
SecurityContextPersistenceFilter
FilterSecurityInterceptor
Basic認証を行う
Security Filter Chainの動作イメージ
• 認可が必要なURLに初回アクセスしたとき
– ※主なFilterに絞っています
12
BasicAuthenticationFilter
ExceptionTranslationFilter
SecurityContextPersistenceFilter
FilterSecurityInterceptor
DispatcherServlet
リクエスト(/admin/foo) レスポンス
HTTPセッションにSecurity Context
がないため、新しく用意する。
用意したSecurity Contextを、
ThreadLocalに入れる
Authorization ID
Context
AuthorizationヘッダからユーザID・
パスワードを取得して認証する。
OKならユーザ情報をSecurity
Contextに入れる
スルー
URLパスに設定された権限と、
Security Contextのユーザ情報の権
限を比較する。OKなら後続の処理
を呼び出す
スルー
例外が投げられた訳
ではないのでスルー
スルー
ユーザ情報入りの
Security ContextをHTTP
セッションに入れる
フォーム認証のサンプル
13
@Configuration
@EnableWebSecurity
public class SampleSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.mvcMatchers("/admin/**").hasAuthority("ADMIN")
.anyRequest().authenticated().and()
.formLogin()
.loginPage("/login").permitAll()
.loginProcessingUrl("/login")
.usernameParameter("username").passwordParameter("password")
.failureUrl("/login?error");
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
・・・ 省略
}
}
フォーム認証を有効にする
ログイン画面のパス。未認証のユーザ
を自動的に遷移させる
認証リクエストのパス。POST前提
認証リクエストに乗せるユーザIDとパス
ワードのパラメータ名ログイン失敗時に遷移
するパス
ログイン画面のサンプル
14
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<body>
<form th:action="@{/login}" method="post">
<input type="text" name="username" />
<input type="text" name="password" />
<input type="submit" value="送信" />
</form>
</body>
</html>
POSTメソッドを指定
※テンプレートエンジンのThymeleafを使用
Security Filter Chainの動作イメージ1/3
• 未認証のユーザが、認可が必要なURLにアクセス
15
UsernamePasswordAuthenticationFilter
ExceptionTranslationFilter
SecurityContextPersistenceFilter
FilterSecurityInterceptor
DispatcherServlet
ログイン画面にリダイレクトHTTPセッションにSecurity Context
がないため、新しく用意する。
用意したSecurity Contextを、
ThreadLocalに入れる
認証のリクエストでは無いので
スルー
リクエスト(/admin/foo)
スルー
未認証なので、
AccessDeniedExceptionをスロー
AccessDeniedExceptionをキャッチ
して、ログイン画面にリダイレクト
するレスポンスを設定。その際、
リクエストの内容をHTTPセッショ
ンに格納する(ログイン後に自動
で遷移するため)
スルー
空のSecurity Contextを
HTTPセッションに入れる。
Security Filter Chainの動作イメージ2/3
• 認証リクエストを送信
16
UsernamePasswordAuthenticationFilter
ExceptionTranslationFilter
SecurityContextPersistenceFilter
FilterSecurityInterceptor
/admin/fooにリダイレクトリクエスト(POSTの/login)
HTTPセッションから空のSecurity
Contextを取得して、ThreadLocal
に入れる。
認証リクエストだと判断して、リク
エストパラメータのID・パスワード
で認証する。認証したユーザ情
報をSecurity Contextに入れる。
HTTPセッションに格納しておいた
リクエストにリダイレクトするレス
ポンスを設定。
DispatcherServlet
ユーザ情報が入った
Security ContextをHTTP
セッションに入れる。
Security Filter Chainの動作イメージ3/3
• /admin/fooにアクセス
17
SecurityContextPersistenceFilter
FilterSecurityInterceptor
レスポンスリクエスト(/admin/foo)
HTTPセッションからSecurity
Context(ユーザ情報入り)を取得
して、ThreadLocalに入れる。
DispatcherServlet
ユーザ情報が入った
Security ContextをHTTP
セッションに入れる。
UsernamePasswordAuthenticationFilter
ExceptionTranslationFilter
認証のリクエストでは無いので
スルー
スルー
URLパスに設定された権限と、
Security Contextのユーザ情報の
権限を比較する。OKなら後続の処
理を呼び出す
スルー
例外が投げられた訳
ではないのでスルー
スルー
Security Filter Chainのログ 1/2
• どのFilterが、どの順番で動いたかをログに出力す
ることが可能
– デバッグに便利
• 設定方法
– ロガーの「org.springframework.security」をDEBUGレベルに
する
– application.propertiesでの設定例
18
logging.level.org.springframework.security=DEBUG
Security Filter Chainのログ 2/2
• 出力例
– 未認証のユーザが、認可が必要なURLにアクセスしたと
きのログ(抜粋)
19
/admin/foo at position 1 of 12 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
/admin/foo at position 2 of 12 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
No HttpSession currently exists
No SecurityContext was available from the HttpSession: null. A new one will be created.
/admin/foo at position 3 of 12 in additional filter chain; firing Filter: 'HeaderWriterFilter'
/admin/foo at position 4 of 12 in additional filter chain; firing Filter: 'CsrfFilter'
/admin/foo at position 5 of 12 in additional filter chain; firing Filter: 'LogoutFilter'
Request 'GET /admin/foo' doesn't match 'POST /logout'
/admin/foo at position 6 of 12 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
Request 'GET /admin/foo' doesn't match 'POST /login'
/admin/foo at position 7 of 12 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
saved request doesn't match
/admin/foo at position 8 of 12 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
/admin/foo at position 9 of 12 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
/admin/foo at position 10 of 12 in additional filter chain; firing Filter: 'SessionManagementFilter'
/admin/foo at position 11 of 12 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
/admin/foo at position 12 of 12 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
Secure object: FilterInvocation: URL: /admin/foo; Attributes: [hasAuthority('ADMIN')]
Voter: org.springframework.security.web.access.expression.WebExpressionVoter@7d30e6, returned: -1
o.s.s.w.a.ExceptionTranslationFilter : Access is denied (user is anonymous); redirecting to authentication entry point
Filterの数と処理
準が表示われる
特別な処理が行われた
らログにでる
さいごに
• Spring Securityの裏の動きのイメージが沸いて、デ
バッグやカスタマイズの作業がし易くなれば幸いで
す。
• おすすめのサイト
– Spring Securityのマニュアルの「The Big Picture」の章
• https://docs.spring.io/spring-
security/site/docs/current/reference/html5/#servlet-
architecture
20
21
ご清聴ありがとうございました
22
ライセンスについて
• JSUGマスコットアイコン(本スライド左下)が残されている場合に限り、本作品(またそれを元にした派生
作品)の複製・頒布・表示・上演を認めます。
• 非商用目的に限り、本作品(またそれを元にした派生作品)の複製・頒布・表示・上演を認めます。
• 本作品のライセンスを遵守する限り、派生作品を頒布することを許可します。

Weitere ähnliche Inhalte

Was ist angesagt?

Was ist angesagt? (20)

[社内勉強会]ELBとALBと数万スパイク負荷テスト
[社内勉強会]ELBとALBと数万スパイク負荷テスト[社内勉強会]ELBとALBと数万スパイク負荷テスト
[社内勉強会]ELBとALBと数万スパイク負荷テスト
 
怖くないSpring Bootのオートコンフィグレーション
怖くないSpring Bootのオートコンフィグレーション怖くないSpring Bootのオートコンフィグレーション
怖くないSpring Bootのオートコンフィグレーション
 
TLS, HTTP/2演習
TLS, HTTP/2演習TLS, HTTP/2演習
TLS, HTTP/2演習
 
マイクロにしすぎた結果がこれだよ!
マイクロにしすぎた結果がこれだよ!マイクロにしすぎた結果がこれだよ!
マイクロにしすぎた結果がこれだよ!
 
さくっと理解するSpring bootの仕組み
さくっと理解するSpring bootの仕組みさくっと理解するSpring bootの仕組み
さくっと理解するSpring bootの仕組み
 
新入社員のための大規模ゲーム開発入門 サーバサイド編
新入社員のための大規模ゲーム開発入門 サーバサイド編新入社員のための大規模ゲーム開発入門 サーバサイド編
新入社員のための大規模ゲーム開発入門 サーバサイド編
 
OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話
OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話
OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話
 
SolrとElasticsearchを比べてみよう
SolrとElasticsearchを比べてみようSolrとElasticsearchを比べてみよう
SolrとElasticsearchを比べてみよう
 
次世代Webコンテナ Undertowについて
次世代Webコンテナ Undertowについて次世代Webコンテナ Undertowについて
次世代Webコンテナ Undertowについて
 
At least onceってぶっちゃけ問題の先送りだったよね #kafkajp
At least onceってぶっちゃけ問題の先送りだったよね #kafkajpAt least onceってぶっちゃけ問題の先送りだったよね #kafkajp
At least onceってぶっちゃけ問題の先送りだったよね #kafkajp
 
最近のやられアプリを試してみた
最近のやられアプリを試してみた最近のやられアプリを試してみた
最近のやられアプリを試してみた
 
40歳過ぎてもエンジニアでいるためにやっていること
40歳過ぎてもエンジニアでいるためにやっていること40歳過ぎてもエンジニアでいるためにやっていること
40歳過ぎてもエンジニアでいるためにやっていること
 
Docker Compose 徹底解説
Docker Compose 徹底解説Docker Compose 徹底解説
Docker Compose 徹底解説
 
こんなに使える!今どきのAPIドキュメンテーションツール
こんなに使える!今どきのAPIドキュメンテーションツールこんなに使える!今どきのAPIドキュメンテーションツール
こんなに使える!今どきのAPIドキュメンテーションツール
 
Spring Bootの本当の理解ポイント #jjug
Spring Bootの本当の理解ポイント #jjugSpring Bootの本当の理解ポイント #jjug
Spring Bootの本当の理解ポイント #jjug
 
Dockerからcontainerdへの移行
Dockerからcontainerdへの移行Dockerからcontainerdへの移行
Dockerからcontainerdへの移行
 
CircleCIのinfrastructureを支えるTerraformのCI/CDパイプラインの改善
CircleCIのinfrastructureを支えるTerraformのCI/CDパイプラインの改善CircleCIのinfrastructureを支えるTerraformのCI/CDパイプラインの改善
CircleCIのinfrastructureを支えるTerraformのCI/CDパイプラインの改善
 
Grafana LokiではじめるKubernetesロギングハンズオン(NTT Tech Conference #4 ハンズオン資料)
Grafana LokiではじめるKubernetesロギングハンズオン(NTT Tech Conference #4 ハンズオン資料)Grafana LokiではじめるKubernetesロギングハンズオン(NTT Tech Conference #4 ハンズオン資料)
Grafana LokiではじめるKubernetesロギングハンズオン(NTT Tech Conference #4 ハンズオン資料)
 
Linux女子部 systemd徹底入門
Linux女子部 systemd徹底入門Linux女子部 systemd徹底入門
Linux女子部 systemd徹底入門
 
今こそ知りたいSpring Batch(Spring Fest 2020講演資料)
今こそ知りたいSpring Batch(Spring Fest 2020講演資料)今こそ知りたいSpring Batch(Spring Fest 2020講演資料)
今こそ知りたいSpring Batch(Spring Fest 2020講演資料)
 

Ähnlich wie Spring fest2020 spring-security

Ähnlich wie Spring fest2020 spring-security (8)

これで怖くない!?コードリーディングで学ぶSpring Security #中央線Meetup
これで怖くない!?コードリーディングで学ぶSpring Security #中央線Meetupこれで怖くない!?コードリーディングで学ぶSpring Security #中央線Meetup
これで怖くない!?コードリーディングで学ぶSpring Security #中央線Meetup
 
Spring Framework ふりかえりと4.3新機能
Spring Framework ふりかえりと4.3新機能Spring Framework ふりかえりと4.3新機能
Spring Framework ふりかえりと4.3新機能
 
Rails4 security
Rails4 securityRails4 security
Rails4 security
 
Scala 初心者向けlt
Scala 初心者向けltScala 初心者向けlt
Scala 初心者向けlt
 
ゼロトラスト三銃士〜Okta x Jamf x Netskopeネタ10連発〜
ゼロトラスト三銃士〜Okta x Jamf x Netskopeネタ10連発〜ゼロトラスト三銃士〜Okta x Jamf x Netskopeネタ10連発〜
ゼロトラスト三銃士〜Okta x Jamf x Netskopeネタ10連発〜
 
WordPressとリスク管理 at 第42回 WordBench大阪
WordPressとリスク管理 at 第42回 WordBench大阪WordPressとリスク管理 at 第42回 WordBench大阪
WordPressとリスク管理 at 第42回 WordBench大阪
 
FuelPHP Osu Nagoya vol.1
FuelPHP Osu Nagoya vol.1FuelPHP Osu Nagoya vol.1
FuelPHP Osu Nagoya vol.1
 
Cloud Foundry にアプリケーションを push する際の典型的な10のエラー
Cloud Foundry にアプリケーションを push する際の典型的な10のエラーCloud Foundry にアプリケーションを push する際の典型的な10のエラー
Cloud Foundry にアプリケーションを push する際の典型的な10のエラー
 

Mehr von 土岐 孝平

試験にでるSpring
試験にでるSpring試験にでるSpring
試験にでるSpring
土岐 孝平
 
Spring3.1概要 データアクセスとトランザクション処理
Spring3.1概要 データアクセスとトランザクション処理Spring3.1概要 データアクセスとトランザクション処理
Spring3.1概要 データアクセスとトランザクション処理
土岐 孝平
 

Mehr von 土岐 孝平 (13)

What's new in Spring Boot 2.6 ?
What's new in Spring Boot 2.6 ?What's new in Spring Boot 2.6 ?
What's new in Spring Boot 2.6 ?
 
SpringベースのCloud Native Application
SpringベースのCloud Native ApplicationSpringベースのCloud Native Application
SpringベースのCloud Native Application
 
Microserviceの今どきのインフラを探る
Microserviceの今どきのインフラを探るMicroserviceの今どきのインフラを探る
Microserviceの今どきのインフラを探る
 
OpenID Connect入門
OpenID Connect入門OpenID Connect入門
OpenID Connect入門
 
これから始めるSpringのwebアプリケーション
これから始めるSpringのwebアプリケーションこれから始めるSpringのwebアプリケーション
これから始めるSpringのwebアプリケーション
 
今さら聞けないDiとspring
今さら聞けないDiとspring今さら聞けないDiとspring
今さら聞けないDiとspring
 
Springを使ったwebアプリにリファクタリングしよう
Springを使ったwebアプリにリファクタリングしようSpringを使ったwebアプリにリファクタリングしよう
Springを使ったwebアプリにリファクタリングしよう
 
Springを何となく使ってる人が抑えるべきポイント
Springを何となく使ってる人が抑えるべきポイントSpringを何となく使ってる人が抑えるべきポイント
Springを何となく使ってる人が抑えるべきポイント
 
業務システムとマイクロサービス
業務システムとマイクロサービス業務システムとマイクロサービス
業務システムとマイクロサービス
 
エッセンシャルCore springハンズオン
エッセンシャルCore springハンズオンエッセンシャルCore springハンズオン
エッセンシャルCore springハンズオン
 
試験にでるSpring
試験にでるSpring試験にでるSpring
試験にでるSpring
 
Spring3.1概要 データアクセスとトランザクション処理
Spring3.1概要 データアクセスとトランザクション処理Spring3.1概要 データアクセスとトランザクション処理
Spring3.1概要 データアクセスとトランザクション処理
 
vFabricを触ろう
vFabricを触ろうvFabricを触ろう
vFabricを触ろう
 

Spring fest2020 spring-security

  • 2. 自己紹介 • 土岐 孝平 • 合同会社 現場指向 • Webアプリ「メモラキー」の運営 • システム開発の支援 • 研修の講師 • 書籍の執筆 2 [改訂新版]Spring入門https://www.memorarchy.com
  • 4. 本セッションの目的 • Spring Securityが裏で何をやっているかを知って、 問題が起きたときのデバッグや、カスタマイズ方法 の調査を円滑にする • キーとなる以下の2つを抑える – Security Filter Chain – Security Context 4 網羅的な機能の説明や、設定ノウハウの説明は行いません
  • 5. Security Filter Chainとは? • Spring Securityが提供するFilter※の繋がり • Servlet Filterの仕組みを使って処理を挟み込む • 各Filterは、認証、URLパスの認可、CSRF防止などの役割 を持つ 5 ※ 個々のFilterは ServletのFilterイン タフェースを実装し ているが、Servletコ ンテナに登録されて いる訳ではない Filter1 FilterX DispatcherServlet Delegating FilterProxy ブラウザ ・・ ・ ・・・ Controller ・・ ・ ServletのFilter Chain ★Security Filter Chain Filter2 Spring MVCのサーブ レット
  • 6. 主なFilter 6 クラス名 役割 CsrfFilter CSRFトークンの発行やチェックを行う HeaderWriterFilter セキュリティ関連のレスポンスヘッダを 設定する BasicAuthenticationFilter Basic認証を行う UsernamePasswordAuthenticationFilter フォーム認証を行う ExceptionTranslationFilter 後続の処理で発生した認証・認可の例 外をキャッチしてハンドリング(エラー画 面に遷移など)する FilterSecurityInterceptor URLのパスの認可を行う SecurityContextPersistenceFilter 「Security Context」を用意して、HTTP セッションやThreadLocalに格納する 次ページで説明
  • 7. Security Context • 認証したユーザ情報(IDや権限など)を格納するオブジェクト • HTTPセッションに保持されるため、リクエストを跨ってユー ザ情報を参照できる • ThreadLocal(スレッド毎にデータを管理してくれる)にも保持 されるため、リクエスト(スレッド)の処理内の任意のタイミング でユーザ情報を参照可能 – Controllerの引数で受けとる – 画面にユーザ情報を表示するときに参照 – staticメソッドでプログラムの任意の箇所で参照 • SecurityContextHolder.getContext() – 認可時(URLのパス、メソッド、画面内の表示非表示)に参照 7
  • 9. Security Filter Chainの作成 • WebSecurityConfigurerAdapter を継承して @EnableWebSecurityを付けたJavaConfigのクラス (@Configurationを付けたクラス)を作成する • @EnableWebSecurityがインポートしている WebSecurityConfigurationクラスの中で、Security Filter Chainのオブジェクトが作成される • 標準的なFilterが自動で登録されるので、メソッドをオーバー ライドして個別の設定を行う 9 @Configuration@Configuration @EnableWebSecurity public class SampleSecurityConfig extends WebSecurityConfigurerAdapter { }
  • 10. 個別の設定のサンプル 10 @Configuration @EnableWebSecurity public class SampleSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .mvcMatchers("/admin/**").hasAuthority("ADMIN") .anyRequest().authenticated().and() .httpBasic(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder(); auth .inMemoryAuthentication() .withUser("foo").password(encoder.encode("passfoo")).authorities("ADMIN").and() .withUser("bar").password(encoder.encode("passbar")).authorities("USER"); } } 「/admin」 で始まるパスは「ADMIN」権限が 必要、それ以外は認証されてればOK Basic認証を有効にする 「foo」ユーザは「ADMIN」権限、「bar」ユーザは 「USER」権限という認証情報をメモリ上に保管
  • 11. 出来上がった主なオブジェクト 11 Authentication Manager UserDetailsService AccessDecision Manager Dispatcher Servlet Delegating FilterProxy ブラウザ ・・ ・ ・・ ・ Controller ServletのFilter Chain ★Security Filter Chain ID・パスワードのチェックを 行う。認証情報は UserDetailsServieから取得 権限のチェックを行う 認証情報を取得。今回はメ モリ上から取得 URLのパスの認可を行う BasicAuthenticationFilter ExceptionTranslationFilter SecurityContextPersistenceFilter FilterSecurityInterceptor Basic認証を行う
  • 12. Security Filter Chainの動作イメージ • 認可が必要なURLに初回アクセスしたとき – ※主なFilterに絞っています 12 BasicAuthenticationFilter ExceptionTranslationFilter SecurityContextPersistenceFilter FilterSecurityInterceptor DispatcherServlet リクエスト(/admin/foo) レスポンス HTTPセッションにSecurity Context がないため、新しく用意する。 用意したSecurity Contextを、 ThreadLocalに入れる Authorization ID Context AuthorizationヘッダからユーザID・ パスワードを取得して認証する。 OKならユーザ情報をSecurity Contextに入れる スルー URLパスに設定された権限と、 Security Contextのユーザ情報の権 限を比較する。OKなら後続の処理 を呼び出す スルー 例外が投げられた訳 ではないのでスルー スルー ユーザ情報入りの Security ContextをHTTP セッションに入れる
  • 13. フォーム認証のサンプル 13 @Configuration @EnableWebSecurity public class SampleSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .mvcMatchers("/admin/**").hasAuthority("ADMIN") .anyRequest().authenticated().and() .formLogin() .loginPage("/login").permitAll() .loginProcessingUrl("/login") .usernameParameter("username").passwordParameter("password") .failureUrl("/login?error"); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { ・・・ 省略 } } フォーム認証を有効にする ログイン画面のパス。未認証のユーザ を自動的に遷移させる 認証リクエストのパス。POST前提 認証リクエストに乗せるユーザIDとパス ワードのパラメータ名ログイン失敗時に遷移 するパス
  • 14. ログイン画面のサンプル 14 <!DOCTYPE HTML> <html xmlns:th="http://www.thymeleaf.org"> <body> <form th:action="@{/login}" method="post"> <input type="text" name="username" /> <input type="text" name="password" /> <input type="submit" value="送信" /> </form> </body> </html> POSTメソッドを指定 ※テンプレートエンジンのThymeleafを使用
  • 15. Security Filter Chainの動作イメージ1/3 • 未認証のユーザが、認可が必要なURLにアクセス 15 UsernamePasswordAuthenticationFilter ExceptionTranslationFilter SecurityContextPersistenceFilter FilterSecurityInterceptor DispatcherServlet ログイン画面にリダイレクトHTTPセッションにSecurity Context がないため、新しく用意する。 用意したSecurity Contextを、 ThreadLocalに入れる 認証のリクエストでは無いので スルー リクエスト(/admin/foo) スルー 未認証なので、 AccessDeniedExceptionをスロー AccessDeniedExceptionをキャッチ して、ログイン画面にリダイレクト するレスポンスを設定。その際、 リクエストの内容をHTTPセッショ ンに格納する(ログイン後に自動 で遷移するため) スルー 空のSecurity Contextを HTTPセッションに入れる。
  • 16. Security Filter Chainの動作イメージ2/3 • 認証リクエストを送信 16 UsernamePasswordAuthenticationFilter ExceptionTranslationFilter SecurityContextPersistenceFilter FilterSecurityInterceptor /admin/fooにリダイレクトリクエスト(POSTの/login) HTTPセッションから空のSecurity Contextを取得して、ThreadLocal に入れる。 認証リクエストだと判断して、リク エストパラメータのID・パスワード で認証する。認証したユーザ情 報をSecurity Contextに入れる。 HTTPセッションに格納しておいた リクエストにリダイレクトするレス ポンスを設定。 DispatcherServlet ユーザ情報が入った Security ContextをHTTP セッションに入れる。
  • 17. Security Filter Chainの動作イメージ3/3 • /admin/fooにアクセス 17 SecurityContextPersistenceFilter FilterSecurityInterceptor レスポンスリクエスト(/admin/foo) HTTPセッションからSecurity Context(ユーザ情報入り)を取得 して、ThreadLocalに入れる。 DispatcherServlet ユーザ情報が入った Security ContextをHTTP セッションに入れる。 UsernamePasswordAuthenticationFilter ExceptionTranslationFilter 認証のリクエストでは無いので スルー スルー URLパスに設定された権限と、 Security Contextのユーザ情報の 権限を比較する。OKなら後続の処 理を呼び出す スルー 例外が投げられた訳 ではないのでスルー スルー
  • 18. Security Filter Chainのログ 1/2 • どのFilterが、どの順番で動いたかをログに出力す ることが可能 – デバッグに便利 • 設定方法 – ロガーの「org.springframework.security」をDEBUGレベルに する – application.propertiesでの設定例 18 logging.level.org.springframework.security=DEBUG
  • 19. Security Filter Chainのログ 2/2 • 出力例 – 未認証のユーザが、認可が必要なURLにアクセスしたと きのログ(抜粋) 19 /admin/foo at position 1 of 12 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter' /admin/foo at position 2 of 12 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter' No HttpSession currently exists No SecurityContext was available from the HttpSession: null. A new one will be created. /admin/foo at position 3 of 12 in additional filter chain; firing Filter: 'HeaderWriterFilter' /admin/foo at position 4 of 12 in additional filter chain; firing Filter: 'CsrfFilter' /admin/foo at position 5 of 12 in additional filter chain; firing Filter: 'LogoutFilter' Request 'GET /admin/foo' doesn't match 'POST /logout' /admin/foo at position 6 of 12 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter' Request 'GET /admin/foo' doesn't match 'POST /login' /admin/foo at position 7 of 12 in additional filter chain; firing Filter: 'RequestCacheAwareFilter' saved request doesn't match /admin/foo at position 8 of 12 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter' /admin/foo at position 9 of 12 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter' /admin/foo at position 10 of 12 in additional filter chain; firing Filter: 'SessionManagementFilter' /admin/foo at position 11 of 12 in additional filter chain; firing Filter: 'ExceptionTranslationFilter' /admin/foo at position 12 of 12 in additional filter chain; firing Filter: 'FilterSecurityInterceptor' Secure object: FilterInvocation: URL: /admin/foo; Attributes: [hasAuthority('ADMIN')] Voter: org.springframework.security.web.access.expression.WebExpressionVoter@7d30e6, returned: -1 o.s.s.w.a.ExceptionTranslationFilter : Access is denied (user is anonymous); redirecting to authentication entry point Filterの数と処理 準が表示われる 特別な処理が行われた らログにでる
  • 20. さいごに • Spring Securityの裏の動きのイメージが沸いて、デ バッグやカスタマイズの作業がし易くなれば幸いで す。 • おすすめのサイト – Spring Securityのマニュアルの「The Big Picture」の章 • https://docs.spring.io/spring- security/site/docs/current/reference/html5/#servlet- architecture 20