本ブログではアイフィリエイトによる収益を得ています。

【Java】Spring Security(5.6.2)で独自の認証を実装する

2022年6月28日火曜日

Java 開発

t f B! P L C


みなさまこんにちは。ムチャ@うつ病SE(@mutoj_rdm821)です。

Spring Securityを使って独自認証を実装したので、方法をまとめておきたいと思います。
Spring Securityのバージョンは5.6.2、SrpingBootは2.6.6です。


ユーザー情報クラスを作成する

ユーザー情報を格納するクラスを作成します。ここではメールアドレスとパスワードを保管するものとして作成しています。必要に応じて属性は追加ください。
  1. package test;
  2.  
  3. import lombok.Data;
  4.  
  5. @Data
  6. public class User {
  7. private String mail;
  8. private String password;
  9. }


UserDetailsクラスを作成する

org.springframework.security.core.userdetails.Userクラスを継承したクラスを作成します。
  1. package test.security;
  2.  
  3. import java.util.Collections;
  4. import java.util.List;
  5.  
  6. import org.springframework.security.core.GrantedAuthority;
  7. import org.springframework.security.core.authority.SimpleGrantedAuthority;
  8.  
  9. import test.User;
  10.  
  11. /**
  12. * ユーザー情報の実装.
  13. */
  14. public class UserDetail extends org.springframework.security.core.userdetails.User {
  15. private User user;
  16. /** ロールはUSERのみ */
  17. private static final List DEFAULT_AUTHORITIES = Collections
  18. .singletonList(new SimpleGrantedAuthority("ROLE_USER"));
  19.  
  20. public UserDetail(User user) {
  21. super(user.getMail(), user.getPassword(), true, true, true, true, DEFAULT_AUTHORITIES);
  22. this.user = user;
  23. }
  24.  
  25. public User getUser() {
  26. return user;
  27. }
  28.  
  29. }

認証プロバイダーを実装する

org.springframework.security.authentication.AuthenticationProviderを実装したクラスを作成します。
  1. package test.security;
  2.  
  3. import java.security.MessageDigest;
  4. import java.security.NoSuchAlgorithmException;
  5. import java.util.Base64;
  6.  
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
  9. import org.springframework.security.authentication.AuthenticationProvider;
  10. import org.springframework.security.authentication.AuthenticationServiceException;
  11. import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
  12. import org.springframework.security.core.Authentication;
  13. import org.springframework.security.core.AuthenticationException;
  14. import org.springframework.stereotype.Service;
  15.  
  16. import test.User;
  17. import test.repository.UserRepository;
  18.  
  19. /**
  20. * 認証プロバイダー.
  21. */
  22. @Service
  23. public class TestAuthenticationProvider implements AuthenticationProvider {
  24.  
  25. @Autowired
  26. private UserRepository repository;
  27.  
  28. /**
  29. * 認証を行う.
  30. */
  31. @Override
  32. public Authentication authenticate(Authentication authentication) throws AuthenticationException {
  33. String mail = (String) authentication.getPrincipal();
  34. String pass = (String) authentication.getCredentials();
  35. User user;
  36. try {
  37. user = repository.findByMail(mail);
  38. } catch (Exception e) {
  39. throw new AuthenticationServiceException("システムエラーが発生しました。",e);
  40. }
  41. String hash = createHash(pass);
  42. if (user != null && hash.equals(user.getPassword())) {
  43. UserDetail detail = new UserDetail(user);
  44. return new UsernamePasswordAuthenticationToken(detail, pass, detail.getAuthorities());
  45. }
  46. System.out.println("ログイン失敗:" + mail);
  47. throw new AuthenticationCredentialsNotFoundException("Authentication failure");
  48. }
  49.  
  50. @Override
  51. public boolean supports(Class authentication) {
  52. return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
  53. }
  54.  
  55. /**
  56. * パスワードのハッシュを計算する.
  57. * @param pass
  58. * @return
  59. */
  60. private String createHash(String pass) {
  61. try {
  62. MessageDigest sha512 = MessageDigest.getInstance("SHA-512");
  63. byte[] data = sha512.digest(pass.getBytes());
  64. Base64.Encoder enc = Base64.getEncoder();
  65. return new String(enc.encode(data));
  66. } catch (NoSuchAlgorithmException e) {
  67. throw new RuntimeException("アルゴリズム名の不正");
  68. }
  69. }
  70. }
authenticateメソッドを実装します。ここでは引数のAuthenticationからメールアドレスとパスワードを取得し、DB等からユーザー情報を取得します。

パスワードはハッシュ化後Base64エンコードされている想定で、復号しています。

認証が成功したら、UsernamePasswordAuthenticationTokenを生成して返します。失敗の場合はAuthenticationCredentialsNotFoundExceptionをスローします。


認証プロバイダーの設定を行う

  1. package test.config;
  2.  
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.context.annotation.Configuration;
  5. import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
  6. import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
  7. import org.springframework.security.config.annotation.web.builders.HttpSecurity;
  8. import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
  9. import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
  10.  
  11. import test.security.TestAuthenticationProvider;
  12.  
  13. @Configuration
  14. @EnableWebSecurity
  15. @EnableGlobalMethodSecurity(prePostEnabled = true)
  16. public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
  17. @Autowired
  18. private TestAuthenticationProvider provider;
  19.  
  20. @Override
  21. protected void configure(AuthenticationManagerBuilder auth) throws Exception {
  22. auth.authenticationProvider(provider);
  23. }
  24. :
WebSecurityConfigerAdapterconfigureメソッドで、引数がAuthenticationManagerBuilderものについて、プロバイダーを設定します。これでログイン認証に 作成したプロバイダーが利用されます。

※Spring Security5.7からWebSecurityConfigerAdapterは推奨されなくなったようで、その場合の方法については調べられていません。


まとめ

Spring Securityで独自認証を実装する方法について解説しました。
DB以外にも別のサービスなどを利用して認証する場合でもつ変えるかと思います。
参考になれば幸いです。

それではみなさまよきJavaライフを(´∀`)ノ


▼ブログを気に入っていただけたらRSS登録をお願いします!
▼ブログランキング参加中!応援よろしくお願いします。

ブログ内検索

自己紹介

猫とガジェットが好きなJava屋さんです。うつ病で休職後退職し、1年半の休養後に社会復帰。・・・が、いろいろあって再び退職。さらに1年休職の後に復帰して、なんとかSE続けてます。茶トラのすずと一緒に生活していましたが、2014年9月4日に亡くなって1人に。

より詳細なプロフィールはこちら↓

↓更新情報を受け取るにはフォローをお願いします!

Instagramでフォロー

※ヘッダー及びアイコンで使用しているドロイド君は、googleが作成、提供しているコンテンツをベースに複製したものです。

▼ココナラでメンターサービスを販売しています。招待コード「C3VG3」で1000ポイントもらえます。
▼欲しい物リスト

ブログ アーカイブ

QooQ