0
0

Spring Security でログイン認証時の入力パラメータをJSONにする方法

Posted at

はじめに

Spring Securityでの認証処理は、ログインフォームに入力された値をPOSTされることが前提です。
しかし、ログイン認証のパラメータをJSONにしたい場合は、デフォルトの仕様だとうまく動きません。

UsernamePasswordAuthenticationFilterを継承したフィルタを作成して行う方法などもありますが、こちらでは、手っ取り早く実装する方法を紹介したいと思います。

やり方

本来の認証処理に近づけたい場合は、フィルタを使用する方法だと思いますが、こちらで紹介する方法は、公式サイトにあった方法を踏襲しています。
ここで紹介する例は、次のURLで紹介している方法を少し改変しています。

任意のコントローラークラス
@RestController
public class SampleLoginController {

    @Autowired
    private AuthenticationManager authenticationManager;
    
    private final SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder.getContextHolderStrategy();
    
    @PostMapping("/login")
    public void login(@Valid @RequestBody LoginRequest loginRequest,
        BindingResult result, HttpServletRequest request, HttpServletResponse response) { 
    
        if (result.hasErrors()) {
            // 入力チェックでエラー
            // ...
            return;
        }
        
        // 認証情報を設定
        UsernamePasswordAuthenticationToken token = UsernamePasswordAuthenticationToken.unauthenticated(
            loginRequest.getUsername(), loginRequest.getPassword()); 
    
        try {
            // 認証
            Authentication authentication = authenticationManager.authenticate(token); 
    
            // セッションの無効化
            request.getSession().invalidate();
        
            // 認証情報をセッションなどに設定
            SecurityContext context = securityContextHolderStrategy.createEmptyContext();
            context.setAuthentication(authentication); 
            securityContextHolderStrategy.setContext(context);
            new HttpSessionSecurityContextRepository().saveContext(context, request, response);
    
            // その他認証が通った後に行いたい処理がある場合はこちらに記述
            // ...
            
        } catch (AuthenticationException e) {
            // 認証NGの場合
            // ...
            
        }
    }

    class LoginRequest {
    
        @NotNull
        private String username;
        
        @NotNull
        private String password;
    
        // getters and setters
    }
}

処理をコントローラーに直接書いちゃうという方法です。
ソースの見通しはこちらの方がわかりやすいかな?と思います。
入力チェック処理を追加したり、認証処理が通った後に現セッションを一旦無効化したり、認証が通らなかった時の処理を追加しています。
このサンプルでは戻り値はvoidですが、戻り値を設定することで、認証が通った場合、認証がNGだった場合、それぞれにおいてJSONを返したりすることもできます。

Security Configは、以下のようにコントローラーにDIするauthenticationManagerを定義します。

SecurityConfig
// デフォルトのAuthenticationManager
@Bean
public AuthenticationManager authenticationManager(final AuthenticationConfiguration authenticationConfiguration) throws Exception {
    return authenticationConfiguration.getAuthenticationManager();
}

そして、更に、未認証の状態で認証が必要な処理にアクセスされた場合の設定をSeurityConfigで行います。

SecurityConfig
	@Bean
	public SecurityFilterChain filterChain(HttpSecurity http)
			throws Exception {

		// 未ログインでアクセスされた場合のURLを設定
		http.exceptionHandling(exception -> exception
				.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/unauthenticated")));

        // ...
    }

フォーム認証関連の設定はSecurityConfigでは一切行いません。
よって、httpSecurity#formLogin() での各種設定は行いません。
それ以外の設定は、ログインフォームでの認証の時と同じです。

最後に

こちらで紹介した方法を紹介しているページは見つからなかったのでここで紹介してみました。
本来のSpring Securityの認証処理に出来るだけ近づけたい場合は、フィルタを別途作成する方法かと思います。ネット上にもいくつか方法は紹介されています。
そちらの方法は、以下のサンプルが参考になると思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0