Spring Security その３〜ログイン画面のカスタマイズ

前回まで
[Spring Security その１〜ログイン機能の実装](https://qiita.com/daiki7010/items/fd4fdf8afd51c3ca9917)
[Spring Security その２〜DB認証](https://qiita.com/daiki7010/items/c838bff7bd456e002e1b)
[Spring Security その2.5〜デフォルトのログアウト画面](https://qiita.com/daiki7010/items/0b9409bb1297c36778d6)

今回はログイン画面を作成し、作成したログイン画面を使用して認証します。

## ログインページの作成
今回はあえて、ユーザ名の項目を「accountId」。パスワードを「pw」としています。
※デフォルトはusernameとpasswordです。
```html
<!doctype html>
<html xmlns:th="http://www.thymeleaf.org">

<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>ログイン</title>


	<!-- Bootstrap CSS -->
	<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet"
		integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
	<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css">
</head>

<body class="bg-light">
	<!--新規登録 -->
	<form action="#" th:action="@{/login}"  method="post">
            <!--/* エラーメッセージ */-->
            <p th:if="${session['SPRING_SECURITY_LAST_EXCEPTION']} != null"
                th:text="${session['SPRING_SECURITY_LAST_EXCEPTION'].message}">
                ログインエラーメッセージ</p>
		<div class="container my-1">
			    <div class="row m-3">
			    	<div class="col-md-4"></div>
					<div class="col-md-4">
						<input type="text" id="accountId" name="accountId" class="form-control" placeholder="ユーザID" required autofocus>
					</div>
					<div class="col-md-4"></div>
			    </div>
				<div class="row m-3">
					<div class="col-md-4"></div>
					<div class="col-md-4">
						<input type="password" id="pw" name="pw" class="form-control" placeholder="パスワード" required>
					</div>
					<div class="col-md-4"></div>
				</div>
				<div class="row m-3">
					<div class="col-md-4"></div>
					<div class="col-md-4">
				       <button class="btn btn-lg btn-primary btn-block" type="submit">ログイン</button>
					</div>
					<div class="col-md-4"></div>
				</div>
		</div>
	</form>
</body>
</html>
```

## SecurityFilterChainの設定
```java
package com.example.conf;

import org.springframework.boot.autoconfigure.security.servlet.PathRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
        .formLogin(login -> login                
                .loginPage("/login").permitAll()	//①
                .defaultSuccessUrl("/toppage")  //②
                .usernameParameter("accountId")    //③
                .passwordParameter("pw")           //④
        		)
        .logout(logout -> logout
        		.logoutSuccessUrl("/login?logout") //⑤
        	    .invalidateHttpSession(true))      //⑥
        .authorizeHttpRequests(authz -> authz
                .requestMatchers(PathRequest.toStaticResources().atCommonLocations())
                .permitAll()
                .anyRequest().authenticated()
        );
        return http.build();
    }
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}
```
①ログインページのURLを指定します（後でこれにひもづくコントローラを設定します。
②ログイン認証成功後の遷移先URLを指定します。
※実はここも少しハマったポイントなので、別途記事を書くつもりです。
③ログインページで指定したユーザ名を入力する項目を指定。今回はaccountIdを指定
④ログインページで指定したパスワードを入力する項目を指定。今回はpwを指定
⑤ログアウトが成功した際の遷移先。
⑥ログアウト時にHTTPセッションを無効にする。（デフォルトもTrueなのであえて指定しなくてもいいかも）

## コントローラの設定
```java
package com.example.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class DemoController {

	@GetMapping("/toppage")
	public String toppage() {
		return "toppage";
	}
	//ここを追加
	@GetMapping("/login")
	public String login() {
		return "login";
	}
}
```

これで完成です。
## 実行してみましょう
http://localhost:8080/login にアクセス

作成したログインページが表示
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555551/8d8e043e-a5f0-af6e-5b4c-f65a0d3053ca.png)


ユーザID、パスワード入力→ログインでdefaultSuccessUrlに指定したtoppageに遷移できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555551/85e83eac-8fe0-8763-bcfb-9beb4668962d.png)