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