みなさまこんにちは。ムチャ@うつ病SE(@mutoj_rdm821)です。
Spring Securityを使って独自認証を実装したので、方法をまとめておきたいと思います。
Spring Securityのバージョンは5.6.2、SrpingBootは2.6.6です。
ユーザー情報クラスを作成する
ユーザー情報を格納するクラスを作成します。ここではメールアドレスとパスワードを保管するものとして作成しています。必要に応じて属性は追加ください。
package test;
import lombok.Data;
@Data
public class User {
private String mail;
private String password;
}
UserDetailsクラスを作成する
org.springframework.security.core.userdetails.Userクラスを継承したクラスを作成します。package test.security;
import java.util.Collections;
import java.util.List;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import test.User;
/**
* ユーザー情報の実装.
*/
public class UserDetail extends org.springframework.security.core.userdetails.User {
private User user;
/** ロールはUSERのみ */
private static final List DEFAULT_AUTHORITIES = Collections
.singletonList(new SimpleGrantedAuthority("ROLE_USER"));
public UserDetail(User user) {
super(user.getMail(), user.getPassword(), true, true, true, true, DEFAULT_AUTHORITIES);
this.user = user;
}
public User getUser() {
return user;
}
}
認証プロバイダーを実装する
org.springframework.security.authentication.AuthenticationProviderを実装したクラスを作成します。package test.security;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.stereotype.Service;
import test.User;
import test.repository.UserRepository;
/**
* 認証プロバイダー.
*/
@Service
public class TestAuthenticationProvider implements AuthenticationProvider {
@Autowired
private UserRepository repository;
/**
* 認証を行う.
*/
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String mail = (String) authentication.getPrincipal();
String pass = (String) authentication.getCredentials();
User user;
try {
user = repository.findByMail(mail);
} catch (Exception e) {
throw new AuthenticationServiceException("システムエラーが発生しました。",e);
}
String hash = createHash(pass);
if (user != null && hash.equals(user.getPassword())) {
UserDetail detail = new UserDetail(user);
return new UsernamePasswordAuthenticationToken(detail, pass, detail.getAuthorities());
}
System.out.println("ログイン失敗:" + mail);
throw new AuthenticationCredentialsNotFoundException("Authentication failure");
}
@Override
public boolean supports(Class authentication) {
return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
}
/**
* パスワードのハッシュを計算する.
* @param pass
* @return
*/
private String createHash(String pass) {
try {
MessageDigest sha512 = MessageDigest.getInstance("SHA-512");
byte[] data = sha512.digest(pass.getBytes());
Base64.Encoder enc = Base64.getEncoder();
return new String(enc.encode(data));
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("アルゴリズム名の不正");
}
}
}
authenticateメソッドを実装します。ここでは引数のAuthenticationからメールアドレスとパスワードを取得し、DB等からユーザー情報を取得します。パスワードはハッシュ化後Base64エンコードされている想定で、復号しています。
認証が成功したら、
UsernamePasswordAuthenticationTokenを生成して返します。失敗の場合はAuthenticationCredentialsNotFoundExceptionをスローします。認証プロバイダーの設定を行う
package test.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import test.security.TestAuthenticationProvider;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private TestAuthenticationProvider provider;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(provider);
}
:
WebSecurityConfigerAdapterのconfigureメソッドで、引数がAuthenticationManagerBuilderものについて、プロバイダーを設定します。これでログイン認証に 作成したプロバイダーが利用されます。※Spring Security5.7から
WebSecurityConfigerAdapterは推奨されなくなったようで、その場合の方法については調べられていません。まとめ
Spring Securityで独自認証を実装する方法について解説しました。
DB以外にも別のサービスなどを利用して認証する場合でもつ変えるかと思います。
参考になれば幸いです。
それではみなさまよきJavaライフを(´∀`)ノ


