こんにちは、くまごろーです。
資格の勉強もひと段落ついたので、年内はポートフォリオの作成に集中することにしました。
Spring Securityを使ってログイン機能を実装しているんですが、Spring Securityはデフォルトでは"username"でログイン処理を行うようになっているんですよね。それをメールアドレスでの認証に変更したかったんですが中々うまくいかず・・・
正解にたどり着けず苦戦したのでここでまとめておきます。
1 Configクラス
【このクラスでやること】
(1)ログインフォームで入力された「メールアドレス」「パスワード」を、SecurityConfigを通して受け取るよう設定する
(2)UserDetailsServiceクラスで、DBからユーザーを参照できるようにする
<SecurityConfig.java>
@Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests().antMatchers("/login", "/register").permitAll().anyRequest().authenticated() .and() .formLogin().loginPage("/login").defaultSuccessUrl("/") .usernameParameter("email") //usernameの値を"email"から取得するよう設定する .passwordParameter("password") .and() .logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")) .and() .rememberMe(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception{ auth //ユーザの設定 //userDetailsServiceで、DBからユーザーを参照できるようにする .userDetailsService(userDetailsService) .passwordEncoder(passwordEncoder()); }
※ usernameParameter(), passwordParameter()で指定する文字列は、htmlのname属性の名前と同名になる。
2 Repositoryクラス
このクラスでは、"email"でユーザーを検索するメソッドを実装する。
<UserRepository.java>
public interface SiteUserRepository extends JpaRepository<SiteUser, Long> { //Emailでユーザーを検索 public SiteUser findByEmail(String email); }
※ Repositoryインターフェースでは、規則に従ってメソッド名を宣言することで、自動実装が利用可能になる。(詳細については以下のページでわかりやすく説明されています。)
以下の3つの要素を規則に従って組み合わせたメソッド名をRepositoryインターフェースに宣言することで、自動実装が利用可能になります。
プレフィックス(find...By read...By query...By count...By get...By)
キーワード
フィールド名
【Spring Data JPA】自動実装されるメソッドの命名ルール - Qiita
3 UserDetailsServiceクラス
【ここでやること】
(1)RepositoryクラスのメソッドでDBからユーザーを検索する
(2)見つかったユーザー情報をSiteUserクラスに格納
(3)ユーザーに応じて権限を設定
(4)User(Details)オブジェクト生成し、認証処理へ
<UserDetailsServiceImpl.java>
@Override public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException{ SiteUser user = userRepository.findByEmail(email); if(user == null) { //ユーザーが見つからなければ、SpringSecurityの以下の例外をthrowする。 throw new UsernameNotFoundException(email + " not found"); } return createUserDetails(user); } public User createUserDetails(SiteUser user) { Set<GrantedAuthority> grantedAuthories = new HashSet<>(); grantedAuthories.add(new SimpleGrantedAuthority("ROLE_" + user.getRole())); return new User(user.getUsername(), user.getPassword(), grantedAuthories); }
4 参考
spring Security ログインフォームの項目とSecurytyConfig、値の受け渡し - Qiita
Spring-Bootでログイン機能を実装してみる - Qiita
【Spring Data JPA】自動実装されるメソッドの命名ルール - Qiita