今回は、Spring MVC上のSpring Securityを利用したプログラムに、Spring Bootの場合に実装していた、Spring Securityのリクエスト毎にCSRFトークンを変える処理とSpring Securityのエラー処理を追加してみたので、そのサンプルプログラムを共有する。
前提条件
下記記事の実装が完了していること。
流用ソース
Spring Bootを使っていた、下記記事のソースコードを流用するものとする。
サンプルプログラムの作成
作成したサンプルプログラムの構成は以下の通り。

なお、上記の赤枠は、「前提条件」のプログラムから変更したプログラムである。
Spring Securityの定義を行うXMLファイルの内容は以下の通りで、前提条件のプログラムに、エラー制御と、CSRFトークンチェックをリクエスト毎に行う対応を追加し、流用ソースの「DemoSecurityConfig.java」と同じような内容を実装している。
<?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トークンチェックをリクエスト毎に行う対応を追加することができる。





