みなさまこんにちは。ムチャ@うつ病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ライフを(´∀`)ノ