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

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

新規登録して質問してみよう
ただいま回答率
85.35%
MySQL Workbench

MySQL Workbenchは、オープンソースのデータベースモデリングツールです。ビジュアルなデータベース設計・SQL開発・サーバー設定・ユーザー管理・バックアップといった様々な管理ツールを備えます。

Spring Security

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

Java

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

ログイン

ログインは、ユーザーがコンピューターシステムにアクセスするプロセスの事を呼びます。

Thymeleaf

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

Q&A

解決済

1回答

2154閲覧

登録されているユーザー情報でログインが出来ない

shinnuko

総合スコア13

MySQL Workbench

MySQL Workbenchは、オープンソースのデータベースモデリングツールです。ビジュアルなデータベース設計・SQL開発・サーバー設定・ユーザー管理・バックアップといった様々な管理ツールを備えます。

Spring Security

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

Java

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

ログイン

ログインは、ユーザーがコンピューターシステムにアクセスするプロセスの事を呼びます。

Thymeleaf

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

0グッド

0クリップ

投稿2020/07/14 15:09

前提・実現したいこと

Java(springboot)で掲示板を作製しています。
ログインページからユーザー情報をフォームに入力し、ログインを行おうとしているのですが、認証失敗になってしまう状態です。
ユーザー登録機能は正しく動作している状態です。

発生している問題・エラーメッセージ

コンソール上、web上共にエラーは検出されていない状態です。
web上では正しいユーザー情報を入力しても、間違ったユーザー情報を入力しても、同じように認証失敗時のページに遷移してしまう状態です。
また、認証失敗時の設定を

.failureUrl("/login/?error") // ログイン処理失敗時の遷移先

上記の様に設定しているのですが、実際に認証失敗時に遷移しているページのURLが

http://localhost:8080/login/login

となっています。

該当のソースコード

WebSecurityConfig

package com.example.demo.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.authentication.configuration.GlobalAuthenticationConfigurerAdapter; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import com.example.demo.dto.JpaUserDetailsServiceImpl; @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override public void configure(WebSecurity web) throws Exception { // セキュリティ設定を無視するリクエスト設定 // 静的リソースに対するアクセスはセキュリティ設定を無視する web.ignoring().antMatchers("/","/css/**", "/datepicker/**", "/img/**"); } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() // 認証が必要となるURLを設定します .antMatchers("/login/**").permitAll() // /loginは認証不要 .antMatchers("/register/").permitAll() .antMatchers("/thread/").permitAll() // /threadURLも認証不要 .antMatchers("/complete").permitAll() .anyRequest().authenticated(); // それ以外はすべて認証された状態じゃなきゃダメ http.formLogin() .loginProcessingUrl("/login/") // 認証処理を起動させるパス .loginPage("/login/") // ログインフォームのパス .failureUrl("/login/?error") // ログイン処理失敗時の遷移先 .defaultSuccessUrl("/") // 認証成功時の遷移先 .usernameParameter("name").passwordParameter("password"); // ユーザ名とパスワード http.logout() .logoutRequestMatcher(new AntPathRequestMatcher("/logout**")) // ログアウト処理を起動させるパス .logoutSuccessUrl("/"); // ログアウト完了時のパス } @Configuration protected static class AuthenticationConfiguration extends GlobalAuthenticationConfigurerAdapter { @Autowired JpaUserDetailsServiceImpl userDetailsService; @Override public void init(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService) .passwordEncoder(new BCryptPasswordEncoder()); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); //パスワードのハッシュ化でBCryptを使う } } }

JpaUserDetailsServiceImpl

package com.example.demo.dto; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Component; import com.example.demo.dao.RegisterRepository; @Component public class JpaUserDetailsServiceImpl implements UserDetailsService { @Autowired private RegisterRepository registerRepository; @Override public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException { Register register = registerRepository.findByName(name); return register; } }

RegisterRepository

package com.example.demo.dao; import org.springframework.data.jpa.repository.JpaRepository; import com.example.demo.dto.Register; import com.example.demo.dto.RegisterprocessDto; public interface RegisterRepository extends JpaRepository<RegisterprocessDto, Integer> { Register findByName(String name); }

Register

package com.example.demo.dto; import java.util.Collection; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import lombok.Data; @Entity @Table(name = "users") @Data public class Register implements UserDetails { @Id @GeneratedValue private Integer user_id; @Column(nullable=false, unique = true) private String name; @Column(nullable=false, length=60) private String password; /* (非 Javadoc) * @see org.springframework.security.core.userdetails.UserDetails#getAuthorities() */ @Override public Collection<? extends GrantedAuthority> getAuthorities() { return null; } /* (非 Javadoc) * @see org.springframework.security.core.userdetails.UserDetails#getUsername() */ @Override public String getUsername() { return this.name; } /* (非 Javadoc) * @see org.springframework.security.core.userdetails.UserDetails#isAccountNonExpired() */ @Override public boolean isAccountNonExpired() { return true; } /* (非 Javadoc) * @see org.springframework.security.core.userdetails.UserDetails#isAccountNonLocked() */ @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { return true; }

UserDetails

package com.example.demo.frontinterface; import java.io.Serializable; import java.util.Collection; import org.springframework.security.core.GrantedAuthority; public interface UserDetails extends Serializable { Collection<? extends GrantedAuthority> getAuthorities();//getAuthorities ユーザーに与えられている権限リストを返却 String getPassword();//登録されているパスワードを返却 String getName();// ユーザー名を返却 boolean isAccountNonExpired();// アカウントの有効期限の状態を判定 boolean isAccountNonLocked();//アカウントのロック状態を判定 boolean isCredentialsNonExpired();//資格情報の有効期限の状態を判定 boolean isEnabled();//有効なユーザーかを判定 }

LoginController

package com.example.demo.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class LoginController { @RequestMapping("/login") public String login() { return "login"; } }

login.html

<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>ログイン</title> </head> <body> <form th:action="login" method="POST"> <table align="center"> <tr> <td> ユーザ名: </td> <td> <input type="text" id="name" name="name"/> </td> </tr> <tr> <td> パスワード: </td> <td> <input type="password" id="password" name="password"/> </td> </tr> <tr> <td> </td> <td align="right"> <button type="submit">ログイン</button> </td> </tr> <tr> <td> </td> <td align="right"> <a href="/register/">新規登録へ</a> <a href="/">フォーム画面へ</a> </td> </tr> </table> </form> </body> </html>

error.html

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <p>ログインできませんでした</p> <a href="/login/">ログイン画面へ</a> </body> </html>

試したこと

デバックモードでログインを実施→
ユーザー名(name)が取得出来ていないのを確認→
login.htmlのinputタグのname=部分とWebSecurityConfigの.usernameParameter部分の不一致が発生していたため修正を実施。

ユーザー名を全角ではなく半角で登録し、ログインを実施→変わらず認証失敗ページに遷移。

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

Java SE8
Eclips Version: 2020-03 (4.15.0)
SpringBoot
Mysql8.0
現在のGithub
参考記事1
参考記事2
参考記事3
MySQL内のデータ

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2020/07/15 01:53

パスワードをエンコードしてるので、登録時のパスワードと認証時のパスワードが異なっている可能性があります。 登録ロジックのソースも掲載は可能でしょうか?
guest

回答1

0

ベストアンサー

とりあえず認証が通るようにするには下記の修正が必要です。

トップページに対する認証除外の設定

トップページ(/)に対する認証除外はWebSecurityではなくHttpSecurityで行います。

WebSecurityConfig.java

java

1@Override 2public void configure(WebSecurity web) throws Exception { 3 4 // ★修正前 5 //web.ignoring().antMatchers("/", "/css/**", "/datepicker/**", "/img/**"); 6 7 // ★修正後 8 web.ignoring().antMatchers("/css/**", "/datepicker/**", "/img/**"); 9 10}

java

1@Override 2protected void configure(HttpSecurity http) throws Exception { 3 http.authorizeRequests() 4 // ★追加 5 .antMatchers("/").permitAll() 6 .antMatchers("/login/**").permitAll() 7 8 // 省略 9}

認証処理を行うURLの変更

認証処理を行うURLとログインページへのURLは別々にする必要があります。この例では/login_processとしていますが、任意です。

WebSecurityConfig.java

java

1@Override 2protected void configure(HttpSecurity http) throws Exception { 3 4 5 http.formLogin() 6 // ★修正前 7 //.loginProcessingUrl("/login/") // 認証処理を起動させるパス 8 9 // ★修正後 10 .loginProcessingUrl("/login_process") 11 .antMatchers("/login/**").permitAll() // /loginは認証不要 12 13 // 省略 14}

上記の修正にあわせてlogin.htmlを下記のようになおします。

修正前

html

1<form th:action="login" method="POST">

修正後

html

1<form th:action="@{/login_process}" method="POST"> 2

RegisterRepositoryの修正

JpaRepositoryインタフェースに指定する総称型とfindByNameメソッドの返す型は同じでなければなりません。
この場合、認証に使う型はRegisterなので、こちらにあわせます。

RegisterRepository.java

java

1// ★修正前 2//public interface RegisterRepository extends JpaRepository<RegisterprocessDto, Integer> { 3// ★修正後 4public interface RegisterRepository extends JpaRepository<Register, Integer> { 5 6 Register findByName(String name); 7 8}

上記の修正にあわせてRegisterService.javaも修正が必要です。createメソッドの呼び出し元では戻り値を使っていなかったのでvoidに変えています。
戻り値を使うのであればそのように修正してください。

java

1public class RegisterService { 2 3/* 4 ★修正前 5 public RegisterprocessDto create(RegisterprocessDto registerprocessDto , String rawPassword) { 6 String encodedPassword = passwordEncoder.encode(rawPassword); 7 registerprocessDto.setPassword(encodedPassword); 8 return registerRepository.save(registerprocessDto); 9 } 10*/ 11 12 // ★修正後 13 public void create(RegisterprocessDto registerprocessDto , String rawPassword) { 14 String encodedPassword = passwordEncoder.encode(rawPassword); 15 Register register = new Register(); 16 register.setName(registerprocessDto.getName()); 17 register.setPassword(encodedPassword); 18 registerRepository.save(register); 19 } 20 21}

パスが正しく設定されていないことで認証エラーになる箇所の対応

register.htmlの以下の部分を修正します。これをなおさないと/register.cssへのアクセスが発生し、このアクセスが認証エラーになります。

修正前

html

1<link rel="stylesheet" href="register.css">

修正後

html

1<link rel="stylesheet" th:href="@{/css/register.css}">

デバッグで便利な設定

application.propertiesに下記の設定を追加しておくとデバッグ時に役に立つことがあります。

logging.level.org.springframework.web = info logging.level.org.springframework.security = debug logging.level.org.hibernate = info logging.level.org.hibernate.SQL = debug logging.level.org.hibernate.type.descriptor.sql.BasicBinder = trace

それとchromeで開発している場合は開発者ツールのnetworkタブでリクエストを見張っておくと、原因を調べるときに役に立ちます。

投稿2020/07/16 10:21

rubytomato

総合スコア1752

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

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

shinnuko

2020/07/16 15:56

非常に分かりやすい解説ありがとうございます。 早速修正を実施してみますので、また改めて報告させて頂きます。
shinnuko

2020/07/18 07:22

アドバイス頂いた部分を修正することで無事ログインが出来るようになりました。 ご協力ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問