SpringBootで独自ログイン画面や認証除外ページ設定

# この記事はこれの続きです

https://qiita.com/waokitsune/items/5e2e071687f8ca354805

# 概要

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/1391a2ca-bfde-0e55-2235-32283bd1610e.png)

# WebScurityConfigクラス新規作成

```java:NekoWebScurityConfig.java
package com.example.demo;


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;


@Configuration
@EnableWebSecurity
public class NekoWebScurityConfig {
	
	
	@Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
		
    	http
    	
    	.authorizeHttpRequests((requests) -> requests
    			
                //アクセス制限除外URL。
                .requestMatchers("/",
                		"/login-input",
                		"/okok/*")
                .permitAll()
                .anyRequest()
                .authenticated()
    			
    			)
    	
    	.formLogin((login) -> login
    			
    			//ユーザーIDとパスワードを受け取るパラメーター名。
                .usernameParameter("username")
                .passwordParameter("password")
                
                //ログイン実行ページ。
                //仮にLoginTryControllerクラスを作ってもその内容は無視されます。
                .loginProcessingUrl("/login-try")
                
                //ユーザーIDとパスワード入力画面。
                .loginPage("/login-input")
                
                //ログイン失敗時遷移先。
                //ログイン失敗用のページを用意しません。
                //それを用意すると
                //『ユーザーIDとパスワード入力画面へのリンクをクリック』
                //という無駄な操作が発生するため。
                .failureUrl("/login-input?error")
                                
                //ログイン成功時遷移先。
                .defaultSuccessUrl("/login-success", true)
                
                .permitAll()

    			)
    	
    	.logout((logout) -> logout
    			
    			//ログアウトを実行するURL。
    			.logoutUrl("/logout")
    			
    			//ログアウト時の遷移先。
    	        .logoutSuccessUrl("/login-input")
    	        
    	      	//HTTPセッションを無効に。
    	        .invalidateHttpSession(true)
    	        
    	        //ログアウト時にクッキーを削除。
    	        .deleteCookies("JSESSIONID")
    	        
    	        .permitAll()
    	        
    			);
    	
    	
    	return http.build();
    	
    	
	}
	
	
}
```

# ユーザーIDとパスワード入力画面用意

```java:LoginInputController
package com.example.demo;


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


@Controller
public final class LoginInputController {

	
	@GetMapping("/login-input")
	public final String main() throws Exception {
		return "/login-input";
	}
	
	
}
```

```html:login-input.html
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
<body>
	
	<h1>login-input</h1>
	
	<form th:action="@{/login-try}" method="POST">
		<div>
			<div>ID</div>
			<input type="text" id="username" name="username" required autofocus />
		</div>
    	<div>
			<div>パスワード</div>
    		<input type="password" id="password" name="password" required />
    	</div>
		<button type="submit" value="go">ログイン</button>
    </form>
    
    <div th:if="${param.error != null}">
	    ログインに失敗しました。
	</div>
    
</body>
</html>
```

# ログイン成功画面用意

```java:LoginSuccessController
package com.example.demo;


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


@Controller
public final class LoginSuccessController {

	
	@GetMapping("/login-success")
	public final String main() throws Exception {
		return "/login-success";
	}
	
	
}
```

```html:login-success.html
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
<body>
	<h1>login-success</h1>
	
	<form th:action="@{/logout}" method="POST">
		<!-- aタグのリンクだとクロスサイトリクエストフォージェリー対策のhiddenパラメータが送られず、セッション破棄されないので注意 -->
		<button type="submit" value="go">ログアウト</button>
	</form>
	
</body>
</html>
```

# ログアウト処理用意

```java:LogoutController
package com.example.demo;

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

@Controller
public final class LogoutController {

	
	@GetMapping("/logout")
	public final String main() throws Exception {
		return "/login-input";
	}
	
	
}
```

# 認証無しで行けるページ

割愛します。

# 動作結果

SpringBoot起動直後にhttp:\//localhost:8080/login-successにアクセスすると下記になります。

**『未ログインなのに認証が必要なページにいきなり行こうとしたので、ログイン画面に飛ばされた』** 形です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/13a37d91-b75e-82eb-e39d-f999a5ede7dc.png)

誤ったIDやパスワードだと…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/378d7702-e3c2-8d58-3928-7d87de596e45.png)

こうなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/c8bc9841-7543-5482-dbb9-df6355f8461b.png)

ログイン成功すれば下記です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/4c1649af-5f07-ced3-feb8-ae793a10fa44.png)

ログアウトボタン押すとこうなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/a6de7d73-ad9f-74e5-ccf5-5b64f8682a4a.png)

# 最終的にはこう

赤枠が追加になったものです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/35ff8d2c-4029-8d45-a29c-3a7112e0793c.png)

# ログアウト機能実装の注意点

https://qiita.com/waokitsune/items/8fabf4915796540e97d1

# この記事の続き

https://qiita.com/waokitsune/items/bcb5ce85a912bc506bac

# 参考サイトさん

https://masahirosuzuki.com/2024/01/20/spring-security-login-1/

https://masahirosuzuki.com/2024/01/23/spring-security-login-2/

https://zenn.dev/sthrok/articles/1a427f7a3f7f9a

# バージョン

Microsoft Windows [Version 10.0.22631.3447]
JAVA 17.0.10
Spring Boot v3.1.11