環境
Springを勉強し始めた者です。
現在SpringBoot2 入門: 基礎から実演までの8-3章、【DBのユーザでログインする】のプログラム(Spring-Security3)を動かしています。
フォルダ構成や開発環境、依存関係は全て書に準拠して作成しています。
依存関係
・SpringWeb ・Lombok ・SpringBootDevTool ・Thymeleaf ・SpringDataJPA ・検証 ・SpringSecurity ・H2DB
現在のエラー
【DBのユーザでログインする】のプログラムを動かしてみているのですが、ユーザの登録までは動くのですがログインができず、画面上にerror.htmlで設定したエラー警告を出されてしまいます。
何度もコードを見直したのですが、原因がわかりません。
コンソール上にエラーは表示されていません。
試したこと
ユーザの登録にH2DBを利用しており、登録が実はできていないことが原因と考えH2コンソールでユーザ情報を確認しようともしたのですが、SpringSecurityが働いてしまいコンソールが開かず、真偽不明な状態です。
エラー警告が呼び出されてしまう原因として下記コード内のuserの値がnullであることが原因と考えています。
UserDetailsServiceImplから一部記載
@RequiredArgsConstructor @Service public class UserDetailsServiceImpl implements UserDetailsService{ private final SiteUserRepository userRepository; //ユーザ特定の為のインタフェース //メソッドの戻り値()で見つかったユーザを返す。見つからなかった場合はSecurityのUsename...をthrowする @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException{ //現在userの値はNull SiteUser user = userRepository.findByUsername(username); if(user == null) { throw new UsernameNotFoundException(username + "not found"); } return createUserDetails(user); }
ここでusernameの内容を表示するとregisterで登録したユーザ名が表示されます。
このusernameはログインフォームで入力した値がそのまま入っているだけであり、H2DBの中からfindByUsernameでユーザ情報が見かったわけではない。
原因はおそらくregisterの処理にある。
しかしfindByUsernameを用いて取得したusernameはnullとなっており、結果userの値もnullになっており、UsernameNotFoundExceptionに投げられてエラー警告を出されているようです。
ここのリポジトリとエンティティを交えた処理を自分でもうまく理解できておらず原因の修正まで至らない状態です。
usernameの値をuserにコピーできれば動くのではと考えていますがうまくいっていません。
以下参考にリポジトリとエンティティを記載
リポジトリ
SiteUserRepository
package com.example.demo.repository; import org.springframework.data.jpa.repository.JpaRepository; import com.example.demo.model.SiteUser; public interface SiteUserRepository extends JpaRepository<SiteUser, Long>{ SiteUser findByUsername(String username); boolean existsByUsername(String username); }
エンティティ
SiteUser
package com.example.demo.model; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.validation.constraints.Email; import javax.validation.constraints.NotBlank; import javax.validation.constraints.Size; import lombok.Getter; import lombok.Setter; @Getter @Setter @Entity public class SiteUser { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Size(min = 2,max = 20) private String username; @Size(min = 4,max = 255) private String password; @NotBlank @Email private String email; private int gender; private boolean admin; private String role; private boolean active = true; }
何卒よろしくお願いします。
追記
プロパティの内容を追記します。
application.properties
spring.datasource.url=jdbc:h2:./testdb spring.jpa.hibernate.ddl-auto=update
SecurityConfig
package com.example.demo.config; 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.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.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import com.example.demo.util.Role; import lombok.RequiredArgsConstructor; @RequiredArgsConstructor @Configuration @EnableWebSecurity public class SeculityConfig extends WebSecurityConfigurerAdapter{ private final UserDetailsService userDetailsService; @Bean public BCryptPasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Override public void configure(WebSecurity web) throws Exception{ //セキュリティ設定を無視(ignoring)するパスを指定する //通常、CSSやJS、INGなどの静的なリソースを指定する web.ignoring().antMatchers("/js/**","/css/**","/webjars/**"); } @Override protected void configure(HttpSecurity http)throws Exception{ http.authorizeRequests() //「/login」をアクセス可能にする //[/registerを追加] .antMatchers("/login","/register").permitAll() //[/admin]にはAdminユーザのみアクセス可能とする .antMatchers("/admin/**").hasRole(Role.ADMIN.name()) .anyRequest().authenticated() .and() .formLogin() //ログイン時のURLを指定 .loginPage("/login") //認証後にリダイレクトする場所を指定 .defaultSuccessUrl("/") .and() //ログアウトの設定 .logout() //ログアウト時のURLを指定 .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) .and() //Remember-Meの認証を許可する。これを指定するとログイン状態の保存ができる .rememberMe(); } @Override protected void configure(AuthenticationManagerBuilder auth)throws Exception{ //userDetailsServiceを利用してDBからユーザを参照できるようにする auth.userDetailsService(userDetailsService) //auth.userDetailsService(userDetailsService) .passwordEncoder(passwordEncoder()); } }
Role
package com.example.demo.util; public enum Role { ADMIN, USER }
Pom.xml内にSTS以外から導入した依存関係の追記部分
<!-- SB Admin2を手動追加(STにパッケージが無いので) --> <dependency> <groupId>org.webjars</groupId> <artifactId>startbootstrap-sb-admin-2</artifactId> <version>4.0.6</version> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>webjars-locator</artifactId> <version>0.40</version> </dependency> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-springsecurity5</artifactId> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>datatables-buttons</artifactId> <version>1.6.1</version> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>datatables-plugins</artifactId> <version>1.10.20</version> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>jszip</artifactId> <version>3.1.0</version> </dependency>
回答1件
あなたの回答
tips
プレビュー