ログイン画面のカスタマイズ方法(HTML変更編)Spring Securityで自作ログインページを作成しよう!
新人
「Spring Securityで自動表示されるログイン画面って、どうやって変更するんですか?」
先輩
「それはSpring Securityのログイン画面のカスタマイズですね。まずはデフォルトの挙動から確認していきましょう!」
新人
「デフォルトってどんな画面なんですか?設定しなくても出てくるんですか?」
先輩
「うん、Spring Securityを導入するだけで、自動的にログイン画面が有効になるんだ。HTMLを書かなくてもログイン画面が表示される仕組みだよ。」
新人
「えっ、自分でHTML書かなくてもいいんですか?」
先輩
「そうそう。でもデザインを変更したい場合は、自分でHTMLファイルを作ってカスタマイズする必要があるんだ。」
1. Spring Securityにおけるログイン画面とは?
Spring Securityは、JavaでWebアプリケーションを開発するときに使われる強力なセキュリティフレームワークです。特に、ログイン画面の自動生成機能は非常に便利で、設定を一切書かなくてもすぐに認証機能を導入できます。
ログイン画面とは、ユーザーがIDやパスワードを入力してアプリケーションにアクセスするための画面です。Spring Securityでは、デフォルトのログイン画面が用意されており、セキュリティ設定を加えるだけで有効になります。
このログイン画面は、HTMLやCSSを書かなくても表示されるようになっており、開発をスムーズに始めることができます。ただし、企業やチームのデザインに合わせたログインページにしたい場合は、ログイン画面のカスタマイズが必要です。
この記事では、ログイン画面のHTMLファイルを自作してカスタマイズする方法を、初心者にもわかりやすく丁寧に解説していきます。
2. デフォルトのログイン画面を確認してみよう
まずは、Spring Securityを導入したときに表示されるデフォルトのログイン画面を確認してみましょう。開発環境は、pleiades+Gradle構成で、@Controllerを使ってWebアプリケーションを構築している前提です。
依存関係は、pleiadesのチェックボックス操作で追加します。たとえば、spring-boot-starter-securityのチェックを入れることで、自動的に必要なライブラリが導入され、Spring Securityの機能がプロジェクトに追加されます。
ログイン画面の動作を確認するために、まずは以下のようなシンプルなコントローラーを作成してみましょう。
@Controller
public class HomeController {
@GetMapping("/")
public String home() {
return "home";
}
}
次に、resources/templates/home.htmlに以下のようなHTMLファイルを配置しておきます。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>ホーム画面</title>
</head>
<body>
<h1>ログイン後に表示されるホーム画面です</h1>
</body>
</html>
この状態でアプリケーションを起動し、ブラウザで http://localhost:8080 にアクセスすると、まだログインしていないため、自動的にSpring Securityのデフォルトログイン画面にリダイレクトされます。
デフォルトのログイン画面では、ユーザー名とパスワードを入力するフォームが表示されます。最初に表示されるログイン画面のURLは以下のとおりです。
http://localhost:8080/login
Spring Bootでは、デフォルトでuserというユーザー名と、ランダムに生成されたパスワードがコンソールに表示されるようになっています。
アプリケーションを起動したときのコンソールログに、次のようなパスワードが表示されます。
Using generated security password: 8f8c5c4a-xxxx-xxxx-xxxx-xxxxxxxxxxxx
このユーザー名とパスワードを使えば、ログイン画面にアクセスして認証を通過できます。ただし、このままではデザインがSpring Securityの標準レイアウトなので、次のステップでは自作のHTMLでログイン画面を作る方法を解説していきます。
3. ログイン画面を自作するには?HTMLファイルを作成しよう
Spring Securityでデフォルトのログイン画面を使用するだけでも機能的には問題ありませんが、デザインや文言を自由に変更したい場合は、自分でログイン画面のHTMLファイルを作成する必要があります。ここでは、ログイン画面のHTMLをどのように作ればよいかを丁寧に説明していきます。
まず、ログインページ用のHTMLファイルは、src/main/resources/templates/ディレクトリの中にlogin.htmlという名前で作成します。これはSpring Bootで標準的に利用されるテンプレートディレクトリで、Thymeleafテンプレートエンジンを使う際に自動的に認識される場所です。
以下に、基本的なログイン画面のHTML例を示します。今回はBootstrapなどの外部スタイルライブラリを使用せず、純粋なHTMLで構成します。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>ログイン</title>
</head>
<body>
<h1>ログイン画面</h1>
<form th:action="@{/login}" method="post">
<div>
<label for="username">ユーザー名:</label>
<input type="text" id="username" name="username"/>
</div>
<div>
<label for="password">パスワード:</label>
<input type="password" id="password" name="password"/>
</div>
<div>
<button type="submit">ログイン</button>
</div>
<div th:if="${param.error}">
<p style="color:red;">ユーザー名またはパスワードが間違っています</p>
</div>
</form>
</body>
</html>
このようにHTMLを作成することで、Spring Securityの自動生成ではなく、自分でデザインしたカスタムログインページを利用できるようになります。もちろん、formのactionには@{/login}と指定して、Spring Securityの認証処理に接続させることがポイントです。
4. セキュリティ設定でログインページをマッピングする
自作のログインページを正しく使うためには、Spring Securityの設定ファイルでログインページのURLを明示的に指定する必要があります。ここではJava Config(クラスで設定を書く方法)を用いて、/loginへのアクセスでlogin.htmlを表示させるように構成します。
設定は、Spring Securityのフィルタチェーンを定義するSecurityFilterChainというBeanの中で行います。以下にその設定例を示します。
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/login").permitAll()
.anyRequest().authenticated()
)
.formLogin(form -> form
.loginPage("/login")
.defaultSuccessUrl("/", true)
.failureUrl("/login?error=true")
.permitAll()
)
.logout(logout -> logout
.logoutSuccessUrl("/login?logout=true")
.permitAll()
);
return http.build();
}
}
この設定では、ログインページとして/loginを指定しており、ログイン成功後は/(ホーム画面)にリダイレクトされるようにしています。失敗した場合は/login?error=trueにリダイレクトされ、HTML側でそのパラメータを読み取ってエラーメッセージを表示する仕組みです。
また、ログアウト後にも/login?logout=trueに遷移するよう設定しており、ログアウトの完了を通知できるようになっています。
セキュリティ設定が完了したら、次にこの/loginというURLに対応するような@Controllerを作成する必要があります。
@Controller
public class LoginController {
@GetMapping("/login")
public String login() {
return "login";
}
}
このコントローラクラスは、URLパス/loginにアクセスがあったときに、login.htmlテンプレートを表示させる役割を担います。@RestControllerではなく、@Controllerを使用することで、HTMLファイルを返す構成になっている点に注意してください。
ここまでの設定で、完全に自作したログイン画面が機能するようになります。ログインページのHTMLと、それをマッピングするセキュリティ設定、さらにコントローラーの役割を明確に分けて実装することが、Spring Securityでログイン画面をカスタマイズする上で重要なポイントです。
5. ログイン失敗時の動作を設定する方法
Spring Securityでログインに失敗した場合、適切なエラーメッセージを表示することはユーザー体験の向上にとても重要です。ログイン失敗時には、リダイレクト先のURLにerror=trueというパラメータが付与されます。これを利用して、ログイン画面側でメッセージを表示することができます。
まず、セキュリティ設定にログイン失敗時の遷移先を指定しておきましょう。すでに設定済みの下記コードの中に、failureUrl("/login?error=true")と記述されています。
.formLogin(form -> form
.loginPage("/login")
.defaultSuccessUrl("/", true)
.failureUrl("/login?error=true")
.permitAll()
)
次に、login.htmlの中で、パラメータerrorがある場合にメッセージを表示するように記述します。Thymeleafのth:ifを使えば、条件付きで表示できます。
<div th:if="${param.error}">
<p style="color: red;">ユーザー名またはパスワードが正しくありません</p>
</div>
このように記述することで、ログイン失敗時に自動で/login?error=trueに遷移し、ログイン画面に赤文字でエラーメッセージが表示されるようになります。
6. ログイン成功後に表示する画面の指定
ログインに成功した後、どの画面に遷移させるかを制御することはとても重要です。ユーザーをダッシュボードやホーム画面に自動で誘導したい場合には、defaultSuccessUrlを使ってリダイレクト先を指定することで実現できます。
すでに設定済みのセキュリティ設定クラス内に、以下のような記述があることを確認してください。
.formLogin(form -> form
.loginPage("/login")
.defaultSuccessUrl("/", true)
.failureUrl("/login?error=true")
.permitAll()
)
defaultSuccessUrl("/", true)と記述することで、ログインに成功した際には常にhttp://localhost:8080/にリダイレクトされるようになります。第二引数をtrueにすることで、直前にアクセスしていたページがあったとしても、それを無視して必ず指定したページに遷移します。
たとえば、管理画面や会員ページにログイン後遷移させたい場合には、次のように変更可能です。
.defaultSuccessUrl("/dashboard", true)
この設定によって、ログイン成功時に確実に指定したURLに遷移させることができるため、ユーザーにとってわかりやすく、直感的な動作を実現できます。
7. ログイン画面の動作確認とよくあるミス
ここまでで、Spring Securityにおけるログイン画面のカスタマイズに必要な設定はすべて整いました。しかし、実際に動かしてみると、うまくログイン画面が表示されなかったり、リダイレクトが機能しなかったりすることがあります。ここでは、初心者がつまずきやすい代表的なミスを紹介し、それぞれの対処法を説明します。
テンプレートファイルの配置場所が間違っている
HTMLファイルをsrc/main/resources/templates/以外の場所に置いてしまうと、Spring Bootがテンプレートとして認識できず、404エラーになります。必ずtemplatesディレクトリにlogin.htmlを配置してください。
Controllerで@GetMappingのパスが違う
たとえば、@GetMapping("/login")と記述すべきところを@GetMapping("/signin")などにしてしまうと、セキュリティ設定で指定した/loginと一致しないため、ページが正しく表示されません。
@GetMapping("/login") // セキュリティ設定と一致させる
public String login() {
return "login";
}
HTMLにThymeleafのnamespaceが書かれていない
th:ifやth:actionなどの属性を使う場合には、HTMLファイルの<html>タグにThymeleafの名前空間を指定しておく必要があります。
<html xmlns:th="http://www.thymeleaf.org">
これを忘れてしまうと、テンプレートが正しく処理されず、ログイン処理が期待通りに動作しなくなります。
ログインエラー時のth:ifが機能しない
エラーメッセージが表示されない原因としてよくあるのが、param.errorのパラメータ名ミスや、条件式の記述漏れです。HTML側でしっかり以下のように書かれているか確認してください。
<div th:if="${param.error}">
<p style="color: red;">ユーザー名またはパスワードが正しくありません</p>
</div>
さらに、ブラウザでの動作確認時には、ログインにわざと失敗して?error=trueのパラメータがURLに付与されているかを確認することで、正しくリダイレクトされているかどうかもチェックできます。
フォームのactionが間違っている
ログインフォームのactionには、@{/login}を指定する必要があります。これを/loginなどに直接書いても問題はありませんが、Thymeleafで記述することで将来の拡張性が高まります。
全体を通して、ログイン画面がうまく表示されない場合は、まず以下を順番に確認するのがよいでしょう:
- HTMLの配置場所が正しいか
- ControllerとURLの一致
- HTMLのnamespace記述
- パラメータによる条件分岐の書き方
- セキュリティ設定でURL指定がされているか
これらを確認することで、Spring Securityのログイン画面カスタマイズにおけるトラブルを未然に防ぐことができます。