セキュリティのFiliterには2種類のフローがある
- ログインせずに
- ログインページにアクセスする場合
- ログインが必要ないページにアクセスする場合
- ログインした状態で
- ログインページにアクセスする場合(ほぼない)
- ログインが必要ないページにアクセスする場合
- ログアウトページにアクセスする場合
認証を求めるページの処理を行う場合
-
これは特定のURLでのみ発動する(1個)
- ログインURLなど
-
実際に処理をするのはAuthenticationManagerが行う
- Managerが順番に子供のAuthenticationProvider(認証手形発行所)を呼び出して処理を行う
- 発行所の粒度は???
- 認証が通らなかった場合、何もしない(次のフィルタに飛ばす)
- 認証が通った場合、SecurityContextHolderにThreadLocalで保存する
- ThreadLocalとは?
- Managerが順番に子供のAuthenticationProvider(認証手形発行所)を呼び出して処理を行う
-
ThreadLocalに保存されたら、その値を[0]のHttpSessionContextIntegrationFilterに返し、そのクラスの中でSecurityContextHolderから手形を取り出し、Sessionに保存される
- 手形がない場合はエラー画面へ飛ばす(次には行かない)
- その後で認証後の処理(リダイレクト)を行う。
- Sessionに保存できたら「認証OK」のURLへ飛ばす(だいたいトップ画面)
- 保存できなかったらエラー画面へ飛ばす(だいたいエラーページ)
認証を求めるページの場合は、ここまでの処理で完結する
ポイント
- 認証手形は、ThreadLoacal -> Sessionの順番で保存される
- 認証後どこの画面に飛ばすかを司っているのはAuthenticationManager
認証を求めないページの処理を行う場合
-
上記の処理は、マッチしたら何かをする、マッチしなければ次に進める、という意味の処理になる
-
AnonymousProcessingFilterはAuthenticationManagerをスルーした(該当ではない)URLでのみ発動する
- ここで、認証手形を発行されていない(ThreadLocal->Sessionに保存されていない)場合、認証手形ではなく、Anonymous認証手形というものを発行する
- Anonymous認証手形が発行されたら、AuthenticationManagerと同じように[0]のSecurityContextHolderにThreadLocalに手形が保存される
-
RequestExceptionTranslationFilterでは、次のFilterSecurityInterceptorでエラーをスローされた場合に発動する
- エラーがない場合は、そのまま何もしない(次のAccessDecisionManagerの処理が行われる)
- エラーがある場合は、AccessDecisionManagerからエラーがスローされ、AccessDenyExeption例外を発生させる。
- ここで何のエラー(認証手形?Anonymous認証手形?)かをチェックし、Anonymous認証手形の派生クラスからのエラーの場合は例外処理を行う
- だいたいログイン画面へ遷移させる
- ここで何のエラー(認証手形?Anonymous認証手形?)かをチェックし、Anonymous認証手形の派生クラスからのエラーの場合は例外処理を行う
-
FilterSecurityInterseptorでAnonymous認証手形が発行されたアクセスを許可するかを確認している
- その子供のAccessDecisionManagerのRole Voterたちが一人づつ確認する
- 全員が許可する場合や1人だけ許可すれば通る場合などのパターンがある
- 問題がある場合は、前の処理のRequestExeptionTranslationFilterにエラーがスローされる
- この許可する人たち(Role Voter)は任意で作れるものとデフォルトのものが存在している????
- その子供のAccessDecisionManagerのRole Voterたちが一人づつ確認する
ポイント
- RequestExeptionTranslationFilterは受け身
- 次の処理でエラーをスローされるのを待っている
- RoleVotorはログインしている(認証手形)を発行されたアクセスに対してもチェックすることが可能
- つまり処理の挙動を変化させることができる
- 処理の結果は(何の)エラーを返すかどうかを決定できる