概要
Spring Boot + Spring Security を用いたユーザーアカウント管理システムにおいて,独自の login 画面を作成し,login ページの URL を /login
ではなく /signin
とするのに少しだけ手間取った.
最初に結論を示し,続けて参考のために過程を伴う詳細を記す.
前提
Spring Security の機能を利用して,ユーザーアカウントの作成,ログイン,ログアウトの最低限の処理を実装したことがある.
独自の login 画面を用いたログイン処理を実装したことがない方は,先に詳細を参照されたい.
環境
- Spring Boot 2.4.4
- Spring Security
- Java 11
- Thymeleaf
結論
Config,Controller,テンプレートファイルの login 画面表示 URL および login 処理実行 URL に,利用したい値 (ここでは /signin
) を指定することで解決する.
@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
/* 中略 */
@Override
protected void configure(HttpSecurity http) throws Exception {
http./* 中略 */
.formLogin()
.loginPage("/signin") // 追記または変更; デフォルト login 画面表示 URL
}
}
@GetMapping("/signin") // 変更
public ModelAndView login(ModelAndView modelAndView) {
modelAndView.setViewName("login");
return modelAndView;
}
<form th:method="post" th:action="@{/signin}"> <!-- 変更 -->
<input type="text" name="username"></td>
<input type="password" name="password"></td>
<input type="submit" value="Sign in"/></td>
</form>
詳細
デフォルトの login ページ URL は /login
なので,login 画面用のテンプレートファイル login.html
(ファイル名はこれに限らない) を作成し,login 用の form に th:action="@{/login}"
を追加すれば, login 画面を独自のテンプレートファイルに差し替えることができる.
<form th:method="post" th:action="@{/login}">
<input type="text" name="username"></td>
<input type="password" name="password"></td>
<input type="submit" value="Sign in"/></td>
</form>
ここで,login 画面を表示する URL を /signin
に変更したいとする.
Controller のマッピング URL を変更し,それ以外はデフォルト (/login
) とした場合,/signin
にアクセスをすれば login 処理は実行できる.
@GetMapping("/signin")
public ModelAndView login(ModelAndView modelAndView) {
}
ただし,Spring Security で「認証済みでない場合に,許可されていないページにアクセスをするとログインページにリダイレクトされる」機能を利用していると,デフォルトのリダイレクト先が /login
であるため独自の login ページが表示されない.
次に,デフォルトの login 画面表示 URL を /signin
に変更するために Config に次の記述を追加する.これに伴い,認証なしで /signin
にアクセスできるよう設定する.
http.authorizeRequests()
.mvcMatchers("/", "/signin").permitAll() // 認証なしで /signin にアクセス可能
.and
.formLogin()
.loginPage("/signin") // デフォルト login 画面表示 URL の変更
このとき,login 処理をするための POST リクエストの URL まで変更される模様.リダイレクトされても独自の login ページが表示されるが,今度は submit をしても login 処理ができなくなる.
テンプレートファイルの form の遷移先も同様に変更することでこの問題は解決する.
<form th:method="post" th:action="@{/signin}">
login 画面を表示する GET リクエスト URL と login 処理を実行する POST リクエスト URL に別の値を指定する
次のように URL を指定する場合の記述を示す.
機能 | URL | HTTP メソッド |
---|---|---|
login 画面表示 | /signin/form | GET |
login 処理実行 | /signin/execute | POST |
http.authorizeRequests()
.mvcMatchers("/", "/signin/**").permitAll() // 変更: /signin -> /signin/**
.and
.formLogin()
.loginPage("/signin/form") // 変更: /signin -> /signin/form
.loginProcessingUrl("/signin/execute") // 追加
@GetMapping("/signin/form") // 変更: /signin -> /signin/form
public ModelAndView login(ModelAndView modelAndView) {
modelAndView.setViewName("login");
return modelAndView;
}
<form th:method="post" th:action="@{/signin/execute}"> <!-- 変更 -->
<input type="text" name="username"></td>
<input type="password" name="password"></td>
<input type="submit" value="Sign in"/></td>
</form>