前提・実現したいこと
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内のデータ
回答1件
あなたの回答
tips
プレビュー