今回は、Spring MVC上のSpring Securityを利用したプログラムに、Spring Bootの場合に実装していた、Spring Securityのリクエスト毎にCSRFトークンを変える処理とSpring Securityのエラー処理を追加してみたので、そのサンプルプログラムを共有する。
前提条件
下記記事の実装が完了していること。
流用ソース
Spring Bootを使っていた、下記記事のソースコードを流用するものとする。
サンプルプログラムの作成
作成したサンプルプログラムの構成は以下の通り。
なお、上記の赤枠は、「前提条件」のプログラムから変更したプログラムである。
Spring Securityの定義を行うXMLファイルの内容は以下の通りで、前提条件のプログラムに、エラー制御と、CSRFトークンチェックをリクエスト毎に行う対応を追加し、流用ソースの「DemoSecurityConfig.java」と同じような内容を実装している。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:sec="http://www.springframework.org/schema/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd"> <!-- ログイン画面のcssファイルとしても共通のdemo.cssを利用するため、 --> <!-- src/main/webapp/resources/static/cssフォルダ下は常にアクセス可能とする --> <sec:http pattern="/resources/static/css/**" security="none"/> <sec:http> <!-- ログイン画面は常にアクセス可能とする --> <sec:intercept-url pattern="/login" access="permitAll" /> <!-- それ以外の画面は全て認証を有効にする --> <sec:intercept-url pattern="/**" access="isAuthenticated()" /> <!-- ログインに成功したら検索画面に遷移する --> <sec:form-login login-page="/login" default-target-url="/" /> <!-- ログアウト時はログイン画面に遷移する --> <sec:logout logout-success-url="/login" /> <!-- エラー発生時はエラー画面に遷移する --> <sec:access-denied-handler error-page="/toError" /> <!-- CSRFトークンのリポジトリを設定する --> <sec:csrf token-repository-ref="csrfTokenRepository" /> <!-- CSRFトークンのセッションキーをリクエスト毎に更新する処理を、 --> <!-- CsrfFilter(CSRFトークンチェックを行うFilter)が呼ばれる前に 実行するようにする --> <sec:custom-filter ref="updSessionCsrfFilter" before="CSRF_FILTER" /> <!-- CSRFトークンをリクエスト毎に更新する処理を、 --> <!-- CsrfFilterが呼ばれた後に実行するようにする --> <sec:custom-filter ref="chgCsrfTokenFilter" after="CSRF_FILTER" /> </sec:http> <sec:authentication-manager> <sec:authentication-provider> <sec:user-service> <!-- ユーザー名「user」、パスワード「pass」が入力されたら ログイン可能とする --> <sec:user name="user" password="pass" authorities="USER" /> </sec:user-service> </sec:authentication-provider> </sec:authentication-manager> <!-- CSRFトークンのリポジトリのBean定義 --> <bean id="csrfTokenRepository" class="org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository" /> <!-- CSRFトークンをリクエスト毎に更新するBean定義 --> <bean id="chgCsrfTokenFilter" class="com.example.demo.ChgCsrfTokenFilter"> <constructor-arg ref="csrfTokenRepository" /> </bean> <!-- CSRFトークンのセッションキーをリクエスト毎に更新するBean定義 --> <bean id="updSessionCsrfFilter" class="com.example.demo.UpdSessionCsrfFilter"> <constructor-arg ref="csrfTokenRepository" /> </bean> </beans> |
その他の赤枠のソースは、流用ソースと同じような修正を行っている。ソースコード内容は、以下のサイトを参照のこと。
https://github.com/purin-it/java/tree/master/spring-mvc-reqtoken-errhandling/demo
なお、今回はエラー時に固定でエラー画面(error.html)に遷移するようになっているが、エラーの種類により画面遷移先を変更することもできる。その実装方法は、以下の記事を参照のこと。
https://terasolunaorg.github.io/guideline/5.4.1.RELEASE/ja/Tutorial/TutorialSecurity.html#id15
サンプルプログラムの実行結果
下記記事の「完成した画面イメージの共有」と同じ結果となる。
ただし、初期表示画面へのアクセスパスは、それぞれ「http://(サーバー名):(ポート番号)/(プロジェクト名)/」と読み替えること。また、一覧画面のページング処理は実装されていない。
要点まとめ
- Spring Security用のXML定義を変更することで、エラー制御や、CSRFトークンチェックをリクエスト毎に行う対応を追加することができる。