質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Spring Security

Spring Securityは、Springのサブプロジェクトの一つでWebアプリケーションに必要な機能を追加します。正規ユーザーであるかを確認するための「認証機能」と、ユーザーのアクセスを制御する「認可機能」を簡単に追加することが可能です。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Thymeleaf

Thymeleaf(タイムリーフ)とは、Java用のテンプレートエンジンで、特定のフレームワークに依存せず使用することが可能です。

Spring Boot

Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

Q&A

解決済

1回答

2010閲覧

【Spring Security】emailとpasswordでログイン認証を行うpart1

退会済みユーザー

退会済みユーザー

総合スコア0

Spring Security

Spring Securityは、Springのサブプロジェクトの一つでWebアプリケーションに必要な機能を追加します。正規ユーザーであるかを確認するための「認証機能」と、ユーザーのアクセスを制御する「認可機能」を簡単に追加することが可能です。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Thymeleaf

Thymeleaf(タイムリーフ)とは、Java用のテンプレートエンジンで、特定のフレームワークに依存せず使用することが可能です。

Spring Boot

Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

0グッド

0クリップ

投稿2019/07/28 09:37

編集2019/07/29 00:26

前提・実現したいこと

Spring Securityでemailとpasswordを用いてログイン認証を行う。

###問題
すでに実装済みのアカウント登録機能で登録したemailをJpaUserDetailsServiceImplのfindByAccountEmailメソッドでDBから引っ張ってこれているにも関わらずhttp://localhost:8080/login/?errorに遷移しログインができない。

該当のソースコード

Account

AccountRepository

1package com.example.demo.entity; 2 3import org.springframework.data.jpa.repository.JpaRepository; 4import org.springframework.data.jpa.repository.JpaSpecificationExecutor; 5import org.springframework.data.jpa.repository.Query; 6import org.springframework.data.repository.query.Param; 7 8import java.util.List; 9public interface AccountRepository extends JpaRepository<Account, Integer>, JpaSpecificationExecutor<Account> { 10 11 @Query(value = "SELECT * FROM accounts WHERE account_email = :account_email AND account_delete_flag = 0", nativeQuery = true) 12 Account findByAccountEmail(@Param("account_email") String accountEmail); 13 14 /** 15 * Emailに紐づくアカウントの件数を取得する。 16 * 17 * @param account_email Email 18 * @return 件数 19 */ 20 21 @Query(value = "SELECT COUNT(*) FROM accounts WHERE account_email = :account_email AND account_delete_flag = 0", nativeQuery = true) 22 int countByAccountEmail(@Param("account_email") String accountEmail); 23 24 /** 25 * 全アカウントを検索する。 26 * 27 * @return 全アカウントのリスト 28 */ 29 @Query(value = "SELECT * FROM accounts WHERE account_delete_flag = 0", nativeQuery = true) 30 List<Account> findAllAccount(); 31} 32

WebSecurityConfig

1package com.example.demo.config; 2 3import com.example.demo.service.JpaUserDetailsServiceImpl; 4import org.springframework.beans.factory.annotation.Autowired; 5import org.springframework.context.annotation.Bean; 6import org.springframework.context.annotation.Configuration; 7import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 8import org.springframework.security.config.annotation.authentication.configuration.GlobalAuthenticationConfigurerAdapter; 9import org.springframework.security.config.annotation.web.builders.HttpSecurity; 10import org.springframework.security.config.annotation.web.builders.WebSecurity; 11import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 12import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 13import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 14import org.springframework.security.crypto.password.PasswordEncoder; 15 16@Configuration 17@EnableWebSecurity 18public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 19 20 @Override 21 public void configure(WebSecurity web) { 22 // 認証状態によらず許可するパス 23 web.ignoring().antMatchers("/favicon.ico", "/css/**", "/js/**", "/bootstrap/css/**", "/bootstrap/js/**", "/jquery/**", "/img/**", "/fonts/**"); 24 } 25 26 @Override 27 protected void configure(HttpSecurity http) throws Exception { 28 29 // SessionFixation対策 30 http.sessionManagement().sessionFixation().newSession(); 31 32 http.authorizeRequests() 33 // 認証状態によらず許可するURL 34 .antMatchers("/").permitAll() 35 .antMatchers("/login").permitAll() 36 .antMatchers("/account/register/**").permitAll() 37 .antMatchers("/resources/**").permitAll() 38 .anyRequest().authenticated(); 39 40 http.formLogin() 41 .loginPage("/login") // ログインページのパス 42 .loginProcessingUrl("/login") // 認証処理を起動させるパス 43 .failureUrl("/login/?error") // ログイン処理失敗時の遷移先 44 .successForwardUrl("/top/loginSuccess") // ログイン成功時の繊維先 45 .usernameParameter("login_id")// ユーザid 46 .passwordParameter("login_password").permitAll(); // パスワード 47 48 http.logout() 49 .logoutUrl("/logout") // ログアウト処理を起動させるパス 50 .logoutSuccessUrl("/login") // ログアウト完了時のパス 51 .deleteCookies("JSESSIONID", "SESSION") 52 .invalidateHttpSession(true).permitAll(); 53 54 } 55 56 @Configuration 57 protected static class AuthenticationConfiguration 58 extends GlobalAuthenticationConfigurerAdapter { 59 60 final JpaUserDetailsServiceImpl userDetailsService; 61 62 @Autowired 63 public AuthenticationConfiguration(JpaUserDetailsServiceImpl userDetailsService) { 64 this.userDetailsService = userDetailsService; 65 } 66 67 @Override 68 public void init(AuthenticationManagerBuilder auth) throws Exception { 69 // 認証するユーザーを設定する 70 auth.userDetailsService(userDetailsService) 71 // 入力値をbcryptでハッシュ化した値でパスワード認証を行う 72 .passwordEncoder(new BCryptPasswordEncoder()); 73 } 74 } 75 76 @Bean 77 public PasswordEncoder passwordEncoder() { 78 return new BCryptPasswordEncoder(); 79 } 80}

JpaUserDetailsServiceImpl

1package com.example.demo.service; 2import com.example.demo.entity.Account; 3import com.example.demo.entity.AccountRepository; 4import org.springframework.beans.factory.annotation.Autowired; 5import org.springframework.security.core.userdetails.UserDetails; 6import org.springframework.security.core.userdetails.UserDetailsService; 7import org.springframework.security.core.userdetails.UsernameNotFoundException; 8import org.springframework.stereotype.Component; 9import org.springframework.transaction.annotation.Transactional; 10import java.util.Objects; 11@Component 12@Transactional 13public class JpaUserDetailsServiceImpl implements UserDetailsService { 14 15 /** アカウントリポジトリ */ 16 private final AccountRepository accountRepository; 17 18 @Autowired 19 public JpaUserDetailsServiceImpl(AccountRepository accountRepository) { 20 this.accountRepository = accountRepository; 21 } 22 23 @Override 24 public UserDetails loadUserByUsername(String accountEmail) throws UsernameNotFoundException { 25 Account account = accountRepository.findByAccountEmail(accountEmail); 26 if (Objects.isNull(account)) { 27 return new Account(); 28 } 29 return account; 30 } 31} 32

試したこと

  1. WebSecurityConfigのfailureUrlをコメントアウト

→依然ログイン失敗、URLに/login?errorが表示される
2. Spring Security関連のブログやQiita等を散見
→解決せず

補足情報(FW/ツールのバージョンなど)

もともとuserIdとpasswordでログイン認証を行なっていたアプリのソースコードを元にemailでログインできるよう編集中

上記の問題でかなり長いこと詰まっているため解決方法ご教示いただけると幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/07/28 09:49

で?エラーログ確認してない人に回答がつくことはないと思うが
退会済みユーザー

退会済みユーザー

2019/07/28 10:02

ご意見いただきありがとうございます。 プログラミング初心者なため至らない点どうかご容赦ください。 コメントの件ですが、ここでのエラーログとはスタックトレースのことでしょうか? 今回はログイン成功先に遷移せず、ログイン失敗先に遷移しているためプログラム上のエラーがありません。 そのためスタックトレース上にもエラーが表示されないためどこが問題かわからない状態です。 私の「エラーログ」に関する受け取り方が間違っていればその点ご指摘ください。 よろしくお願いいたします。
退会済みユーザー

退会済みユーザー

2019/07/28 10:29

おそらく認証で「BadCredentialsException」か「IllegalArgumentException("Bad strength")」が投げられてるきがするんだが
退会済みユーザー

退会済みユーザー

2019/07/28 10:42

ちなみに一応確認しておこう(w SELECT * FROM accounts WHERE account_email = :account_email AND account_delete_flag = 0 AND account_password = :account_password :account_email は あなたが画面で入力したメールアドレス :account_password は あなたが画面で入力したパスワード で1件の返却があるならログインできません。
退会済みユーザー

退会済みユーザー

2019/07/28 11:44

回答ありがとうございます。 1. BadCredentialsException等のエラーメッセージは見受けられませんでした。 2. JpaUserDetailsServiceImplの中でオーバーライドしているUserDetailsのloadUserByUsernameはemailの値をキーにしてアカウント情報の存在を確認するだけという認識でしたので、記載いただいた「AND account_password = :account_password」を含むクエリ文は書いていません。 その上で「1件の返却があるならログインできない」という件について詳細お聞きすることは可能でしょうか? お手数おかけしますがよろしくお願いいたします。
rubytomato

2019/07/28 22:48

accountsテーブルに登録したデータは動作検証用だと思うのですが、データはinsert文を直接実行して登録されたのでしょうか? それともアカウント登録画面も実装済みで画面から登録されたのでしょうか?
退会済みユーザー

退会済みユーザー

2019/07/28 22:51

コメントありがとうございます。 こちらアカウント登録画面が実装済で画面上から登録いたしました。 なおパスワードはBCryptPasswordEncoderを使用しハッシュ化した状態で登録しております。
rubytomato

2019/07/28 23:00

ご確認ありがとうございます。 それではフレームワークのバージョンと、差し支えなければpom.xmlとjavaソースコードについてはimport文も質問に記載をお願いできますでしょうか。
退会済みユーザー

退会済みユーザー

2019/07/29 00:32

文字数制限のため下記リンクにpom.xml追記とTopコントローラーとlogin.htmlの移動を行いました。 見にくくて申し訳ありませんがよろしくお願いいたします。 https://teratail.com/questions/203137にpom.xml
guest

回答1

0

ベストアンサー

セッションに保存された例外は故意的じゃないとログに出なかったためちゃんと回答しておくか・・

@Override public boolean isAccountNonExpired() { // false : アカウント有効期限切れ return false; } @Override public boolean isAccountNonLocked() { // false : アカウントロック中 return false; } @Override public boolean isCredentialsNonExpired() { // false : パスワード有効期限切れ return false; } @Override public boolean isEnabled() { // false : アカウント無効 return false; }

うん、ログインできないのは当たり前だね

投稿2019/07/29 01:07

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/07/29 01:11

ちなみに isEnabled() == false => DisabledException isAccountNonLocked() == false =>LockedException isAccountNonExpired() == false => AccountExpiredException isCredentialsNonExpired() == false => CredentialsExpiredException dbPassword != inputHashPassword => BadCredentialsException username == "" => UsernameNotFoundException という例外が発生しています。
退会済みユーザー

退会済みユーザー

2019/07/29 01:19

Entityは完全に見落としていました、、 お付き合いいただきありがとうございます。 おそらくご指摘いただいた内容で解決できると思いますので帰宅次第確認させていただきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問