4
1

More than 1 year has passed since last update.

【Spring Boot】UserDetailsService を使用せずに Spring Security で認証を行う。

Last updated at Posted at 2022-08-19

本文の目的

Spring Securityを使った実装を行おう、と思った時にネットで検索すると、
UserDetailsServiceインターフェイスのloadUserByUsername​(String username)メソッドにて実装を行っている例を多く見かけますが、これはusernameのみでユーザ検索をする設計になっており、usernameとpassword両方で検索するようにはなっていません。
多くの場合は、username(やid,emailなど)とpasswordの両方で認証を行いたい、かと思いますので、UserDetailsService を使用しないで実装してみましたので、備忘としてここに残しておきます。

前提

前回、こちらでUserDetailsServiceを使用しての実装を行っており、今回はその差分のみの記載である。

前回との変更点

  • 前回は、CustomUserDetailsServiceクラスでUserDetailsServiceをimplementsし、loadUserByUsername​(String username)メソッドにて実装を行ったが、今回はAbstractUserDetailsAuthenticationProviderクラスを継承したクラスを作成することで、usernameとpassword両方で検索を行う。

構成

構成は下記の通り。
前回との差分も記載している。
image.png

AbstractUserDetailsAuthenticationProvider クラスを継承したクラスを作成する

UserDetailsServiceを実装しない代わりに、AbstractUserDetailsAuthenticationProvider クラスを継承したクラスを作成する。
AbstractUserDetailsAuthenticationProvider クラスは、ユーザー名とパスワードを認証(比較)するAuthenticationProvider インターフェイスを実装したものである。AuthenticationProviderを直接実装してもよいが、AuthenticationProviderのBeanをAbstractUserDetailsAuthenticationProviderを利用して作ることで、ユーザ名とパスワードを利用した認証処理を簡単に作成できるようなので、今回はそれで実装する。

CustomAbstractUserDetailsAuthenticationProvider.java
package com.example.authentication;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

import com.example.entity.User;
import com.example.repository.UserRepository;

public class CustomAbstractUserDetailsAuthenticationProvider 
extends AbstractUserDetailsAuthenticationProvider // AbstractUserDetailsAuthenticationProviderを継承する
{
	
	@Autowired
	private UserRepository userRepository;
	
    // @EnableWebSecurityをつけたconfigクラスにてBCryptPasswordEncoderをBean登録しているので、ここで注入する。
	@Autowired
	private BCryptPasswordEncoder bCryptPasswordEncoder;

    // UserDetails に何かしらの追加チェックを行いたい場合はここに実装。今回は要件にないので実装なし。
	@Override
	protected void additionalAuthenticationChecks(UserDetails userDetails,
			UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {}

	@Override
	protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication)
			throws AuthenticationException {
		String password = (String) authentication.getCredentials(); // authenticationからpasswordを取得
		User user = userRepository.findByName(username); // usernameでDBの検索を行う。
		if(bCryptPasswordEncoder.matches(password, user1.getPassword())) { // 入力されたパスワードとDBにあったパスワードが一致するか判定
			return new CustomUserDetails(user); // 一致したらUserDetailsをnewしてreturn
		}else {
			throw new UsernameNotFoundException("user not found"); // 一致しなかったらUsernameNotFoundExceptionをスロー
		}
		
	}

}

今作成したCustomAbstractUserDetailsAuthenticationProviderをBean登録する

MyConfigure.java
package com.example.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationProvider;

import com.example.authentication.CustomAbstractUserDetailsAuthenticationProvider;

@Configuration
public class MyConfigure {
	
    // 今作成したCustomAbstractUserDetailsAuthenticationProviderをBean登録する。
	@Bean
	public AuthenticationProvider getAuthenticationProvider() {
		return new CustomAbstractUserDetailsAuthenticationProvider();
	}
	
}

終わりに

loadUserByUsername​を使っていた時のもやもや解消のために実装しました。UserDetailsServiceを使わずに実装したいと思っている方の一助に少しでもなれば幸いです。
間違っている部分もあるかと思いますので、その際はご指摘頂ければと思います。

参考文献

Spring SecurityでDB認証をする | Spring側
github.com/yukihane/hello-java/
Spring Bootで、ユーザ名とパスワードを指定した認証処理の実装方法
UserDetailsServiceのloadUserByUsernameの存在意義がよくわからないです
インターフェース AuthenticationProvider
クラス AbstractUserDetailsAuthenticationProvider
Spring Securityで独自の認証項目を追加する
Spring Securityのカスタム認証-AuthenticationProvider vs UserDetailsS​​ervice

4
1
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
4
1