はてなシスアーキ(自称)の技術ブログこの広告は、90日以上更新していないブログに表示しています。Securityのお話ハーイ!僕です。Securityと戦っています。今のプロジェクトでセキュリティまわりを僕が担当しているのでね。Securityです。いやね、これね、ちょっと僕には難しすぎるんじゃない?「人類には早すぎたのだ!!*1」と、突然机の前で発狂しながら仕事してます。周りの人はびっくりさせてごめんなさい。Securityについて纏めてみようと思います。Securityは主にサーブレットフィルターをもちいてWebアプリケーションのセキュリティ機能を実現しています。Securityをマスターした気分になります。Filterはインタフェースなので、セキュリティ機能を実現するには具体的な実装が必要です。Securityの主役は、「springSecurityFilterChain」という名前でBean定義されたサーブレットフィルターです。そのインスタンスはFilterChainProxyクラスのオブジェクトです。Proxy(代理)という名前が付いているとおり、このクラス自身は具体的なセキュリティ機能を提供していません。SecurityFilterChainでは、どのようにセキュリティ機能を提供しているのか?SecurityFilterChainインタフェースに処理を委譲することで実現しています。FilterChainProxyクラスは複数のSecurityFilterChainインタフェースを保持してます。SecurityFilterChainはmatches()メソッドとgetFilters()メソッドを定義したインタフェースです。FilterChainProxyがクライアントからリクエストを受けると、順番にSecurityFilterChainのmatches()メソッドを呼び出します。matches()メソッドからtrueが返却されたSecurityFilterChainに対して、getFilters()メソッドを呼び出し、返却されたFilter群に処理を委譲することでセキュリティ機能を実現しています。下に示すのが、そのコードの一部です。null;}この内容からわかるとおり、複数のSecurityFilterChainを用いることで、リクエスト毎に異なるセキュリティ機能を適用することが可能となります。「public/**」に一致するURLに送信されたリクエストにはSecurity機能は適用しないけど、「private/**」に一致するURLに送信されたリクエストにはセキュリティ機能を適用するなどです。かっこいいですね!コードからわかるように、最初にmatchしたSecurityFilterChainに処理を委譲する為、順番が重要になります。ここら辺の話はWebSecurityConfigurerAdapterのところで出てきます。上のクラス図の「AnySecurityFilter」は実際の存在するクラスではなく、認証・認可など、各種セキュリティ機能を提供するFilter実装クラスの総称です。HttpFirewall少し話はそれますが、FilterChainProxyクラスはHttpFirewallを保持しています。このインタフェースの機能を用いることで、ディレクトリトラバーサル攻撃やHTTPレスポンス分割攻撃に対するセキュリティを実現しています。このインタフェースのデフォルト実装はDefaultHttpFirewallクラスです。これらの機能はサーブレットリクエストやサーブレットレスポンスのラッパーを用いることで実現しているようです*2。DelegatingFilterProxyFilterChainProxyはspringSecurityFilterChainというフィルタ名で定義されたDelegatingFilterProxyクラスから呼ばれます。ここら辺は混乱しました。通常、Bean定義されたサーブレットフィルタは自動的にサーブレットコンテナに登録されるみたいですが、どうも同じフィルタ名で定義されたフィルタがすでに存在している場合、自動登録の対象にはならないようです。DelegatingFilterProxyクラスは自身のフィルタ名でBean定義されたサーブレットフィルタをDIコンテナから取り出して、そのサーブレットフィルタに処理を委譲するみたいです。3.0以降からサーブレットコンテナの初期化処理をJavaのコードで行うことが出来るようになったので、それ以前はDelegatingFilterProxyのようなBean定義されたサーブレットフィルタを取り出して実行するような仕組みが必要だったのだと思います。今までの話の全体図が次のとおりです。Configのお話WebSecurityとHttpSecurityFilterChainProxyはWebSecurityクラスでインスタンス生成されます。SecurityFilterChainの実装はDefaultSecurityFilterChainクラスで、WebSecurityクラスやHttpSecurityクラスから作成されます。WebSecurityクラスもHttpSecurityクラスもクラス名からは分かりづらいですが、ビルダークラスです。WebSecurityクラスやHttpSecurityクラスには、サーブレットを生成する上で便利なメソッドがたくさん用意されています。このクラスの操作を理解することで、自由自在にシステム要件にあったセキュリティ機能が構築できるのですよ!そして、WebSecurityクラスやHttpSecurityクラスのメソッドを実際に呼び出して設定するのがConfigureクラスになります。WebSecurityConfigurerAdapterWebSecurityConfigurerAdapterクラスは1つのHttpSecurityクラスのインスタンスを生成します。このクラスは継承して使われることを想定されていますが、このクラスの継承クラスの数だけ、SecurityFilterChainが出来上がると思っていいでしょう。SecurityFilterChainは順番が重要だという話をしました。WebSecurityConfigurerAdapterはOrderアノーテーションなどを用いることで、順番を定義します。その順番に従い、SecurityFilterChainのmatches()メソッドが呼ばれる順番が決まります。デフォルトの順序は100になっています。最後にセキュリティ環境の話。WebSecurityConfigurationクラスがspringSecurityFilterChainという名前でBean定義しており、FilterChainProxyのインスタンスをwebSecurityのbuild()メソッドで生成しています。このクラスがWebSecurityConfigurerAdapterの継承クラスと連携して、webSecurityの設定処理を呼び出します。下に示すのが、そのコードの一部です。AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAMEは、"springSecurityFilterChain"という文字列のコンスタント値です。webSecurity.build();}このクラスがConfiguration定義されることで、セキュリティ機能が有効になるんですね!そして、EnableWebSecurityアノーテーションがこのConfiguration定義をimportしています。EnableWebSecurityアノーテーションを定義すると、セキュリティ機能全般が有効になるということなのです!まるで魔法のようだ!さらにさらに、SpringBootWebSecurityConfigurationがこのEnableWebSecurityアノーテーションを自動定義する機能を備えています。SpringBootで自動的にセキュリティ機能が有効にできるのは、SpringBootWebSecurityConfigurationのおかげなのです!まとめ今回作成した全体のクラス図です。Securityのアーキテクチャ部分に特化した記事です。Securityを抑えるなら、UserDetailsServiceやAuthenticationProviderまわりの話も抑えておいたほうがいいようです。OAuth2まわりの話を書きます。1...2014-08-03アジャイルAPI設計時代の到来!?APIデザインの極意を読みました。月別アーカイブ参加グループプログラミングはてなブログをはじめよう!kozakeさんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。