前提・実現したいこと
Spring徹底入門という本を参考に、会議室予約システムを作っています。
現在Spring Securityを使ってログイン機能の実装を行っているのですが、上手くいきません。
ログインフォームに、正しいユーザー名とパスワードを入力してもエラーになってしまいます。
コンソールログを確認しても、エラーメッセージなどは出ていないのでどこの処理が問題なのかはっきりとしません。
実行環境
OS :windows
IDE :Eclipse pleiades-2019-12
Spring Boot バージョン2.4.0
PostgreSQL 13
※参考書に記載されているSpringBootのバージョンは「1.3.5」と古いものになります。
※ログインフォームのHTMLには、デモ用にユーザーaaaaの情報を初期値としてあらかじめ設定しています。
コンソールログ画面
2020-12-22 13:43:51.071 DEBUG 9048 --- [nio-8080-exec-4] org.hibernate.SQL : select user0_.user_id as user_id1_3_0_, user0_.first_name as first_na2_3_0_, user0_.last_name as last_nam3_3_0_, user0_.password as password4_3_0_, user0_.role_name as role_nam5_3_0_ from usr user0_ where user0_.user_id=? 2020-12-22 13:43:51.078 TRACE 9048 --- [nio-8080-exec-4] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [VARCHAR] - [aaaa]
該当のソースコード
xml
1<?xml version="1.0" encoding="UTF-8"?> 2<project xmlns="http://maven.apache.org/POM/4.0.0" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 5 <modelVersion>4.0.0</modelVersion> 6 <parent> 7 <groupId>org.springframework.boot</groupId> 8 <artifactId>spring-boot-starter-parent</artifactId> 9 <version>2.4.0</version> 10 <relativePath /> <!-- lookup parent from repository --> 11 </parent> 12 <groupId>mrs</groupId> 13 <artifactId>mrs</artifactId> 14 <version>0.0.1-SNAPSHOT</version> 15 <name>mrs</name> 16 <description>Demo project for Spring Boot</description> 17 18 <properties> 19 <java.version>11</java.version> 20 </properties> 21 22 <dependencies> 23 <dependency> 24 <groupId>org.springframework.boot</groupId> 25 <artifactId>spring-boot-starter-data-jpa</artifactId> 26 </dependency> 27 <dependency> 28 <groupId>org.springframework.boot</groupId> 29 <artifactId>spring-boot-starter-thymeleaf</artifactId> 30 </dependency> 31 <dependency> 32 <groupId>org.springframework.boot</groupId> 33 <artifactId>spring-boot-starter-web</artifactId> 34 </dependency> 35 36 <dependency> 37 <groupId>org.postgresql</groupId> 38 <artifactId>postgresql</artifactId> 39 <scope>runtime</scope> 40 </dependency> 41 <dependency> 42 <groupId>org.springframework.boot</groupId> 43 <artifactId>spring-boot-starter-test</artifactId> 44 <scope>test</scope> 45 </dependency> 46 47 <!-- Date and Time API --> 48 <dependency> 49 <groupId>org.thymeleaf.extras</groupId> 50 <artifactId>thymeleaf-extras-java8time</artifactId> 51 </dependency> 52 53 <!-- Validation --> 54 <dependency> 55 <groupId>org.springframework.boot</groupId> 56 <artifactId>spring-boot-starter-validation</artifactId> 57 </dependency> 58 59 60 <!-- springsecurity --> 61 <dependency> 62 <groupId>org.springframework.boot</groupId> 63 <artifactId>spring-boot-starter-security</artifactId> 64 </dependency> 65 <dependency> 66 <groupId>org.thymeleaf.extras</groupId> 67 <artifactId>thymeleaf-extras-springsecurity5</artifactId> 68 </dependency> 69 70 </dependencies> 71 72 <build> 73 <plugins> 74 <plugin> 75 <groupId>org.springframework.boot</groupId> 76 <artifactId>spring-boot-maven-plugin</artifactId> 77 </plugin> 78 </plugins> 79 </build> 80 81</project> 82
User
1package mrs.domain.model; 2 3import java.io.Serializable; 4 5import javax.persistence.Entity; 6import javax.persistence.EnumType; 7import javax.persistence.Enumerated; 8import javax.persistence.Id; 9import javax.persistence.Table; 10 11 12//会議室予約システムを利用するユーザー情報を格納するテーブル 13//Userエンティティー 14@Entity 15@Table(name = "usr") 16public class User implements Serializable { 17 18 @Id 19 private String userId; 20 private String password; 21 private String firstName; 22 private String lastName; 23 24 @Enumerated(EnumType.STRING) 25 private RoleName roleName; 26 27 public String getUserId() { 28 return userId; 29 } 30 31 public void setUserId(String userId) { 32 this.userId = userId; 33 } 34 35 public String getPassword() { 36 return password; 37 } 38 39 public void setPassword(String password) { 40 this.password = password; 41 } 42 43 public String getFirstName() { 44 return firstName; 45 } 46 47 public void setFirstName(String firstName) { 48 this.firstName = firstName; 49 } 50 51 public String getLastName() { 52 return lastName; 53 } 54 55 public void setLastName(String lastName) { 56 this.lastName = lastName; 57 } 58 59 public RoleName getRoleName() { 60 return roleName; 61 } 62 63 public void setRoleName(RoleName roleName) { 64 this.roleName = roleName; 65 } 66 67} 68
UserRepository
1package mrs.domain.repository.user; 2 3import javax.persistence.LockModeType; 4 5import org.springframework.data.jpa.repository.JpaRepository; 6import org.springframework.data.jpa.repository.Lock; 7import org.springframework.transaction.annotation.Transactional; 8 9import mrs.domain.model.User; 10 11 12@Transactional 13public interface UserRepository extends JpaRepository<User, String>{ 14 15 @Lock(LockModeType.PESSIMISTIC_WRITE) 16 User findOneForUpdateByUserId(String username); 17 18} 19
ReservationUserDetails
1package mrs.domain.service.user; 2 3import java.util.Collection; 4 5import org.springframework.security.core.GrantedAuthority; 6import org.springframework.security.core.authority.AuthorityUtils; 7import org.springframework.security.core.userdetails.UserDetails; 8 9import mrs.domain.model.User; 10 11//springsecurityで定義されているUserDetailsを実装する 12public class ReservationUserDetails implements UserDetails { 13 14 private final User user; 15 16 public ReservationUserDetails(User user) { 17 18 this.user = user; 19 } 20 21 public User getUser() { 22 return user; 23 } 24 25 @Override 26 public Collection<? extends GrantedAuthority> getAuthorities() { 27 return AuthorityUtils.createAuthorityList("ROLE" + this.user.getRoleName().name()); 28 } 29 30 @Override 31 public String getPassword() { 32 return this.user.getPassword(); 33 } 34 35 @Override 36 public String getUsername() { 37 return this.user.getUserId(); 38 } 39 40 @Override 41 public boolean isAccountNonExpired() { 42 return true; 43 } 44 45 @Override 46 public boolean isAccountNonLocked() { 47 return true; 48 } 49 50 @Override 51 public boolean isCredentialsNonExpired() { 52 return true; 53 } 54 55 @Override 56 public boolean isEnabled() { 57 return true; 58 } 59} 60
ReservationUserDetailsService
1package mrs.domain.service.user; 2 3import org.springframework.beans.factory.annotation.Autowired; 4import org.springframework.security.core.userdetails.UserDetails; 5import org.springframework.security.core.userdetails.UserDetailsService; 6import org.springframework.security.core.userdetails.UsernameNotFoundException; 7import org.springframework.stereotype.Service; 8 9import mrs.domain.model.User; 10import mrs.domain.repository.user.UserRepository; 11 12@Service 13public class ReservationUserDetailsService implements UserDetailsService { 14 15 @Autowired 16 UserRepository userRepository; 17 18 @Override 19 public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 20 21 //ユーザー取得処理はUserRepositoryに委譲 22 User user = userRepository.findById(username).get(); 23 if (user == null) { 24 throw new UsernameNotFoundException(username + " is not found"); 25 } 26 27 //ユーザーの認証・認可処理はReservationUserDetailsに委譲 28 return new ReservationUserDetails(user); 29 } 30} 31
WebSecurityConfig
1package mrs; 2 3import org.springframework.beans.factory.annotation.Autowired; 4import org.springframework.context.annotation.Bean; 5import org.springframework.context.annotation.Configuration; 6import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 7import org.springframework.security.config.annotation.web.builders.HttpSecurity; 8import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 9import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 10import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 11import org.springframework.security.crypto.password.PasswordEncoder; 12 13import mrs.domain.service.user.ReservationUserDetailsService; 14 15@Configuration 16 17//springsecurityのweb連帯機能(CSRF対策など)を有効にする 18@EnableWebSecurity 19public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 20 21 @Autowired 22 ReservationUserDetailsService userDetailsService; 23 24 @Bean 25 PasswordEncoder passwordEncoder() { 26 return new BCryptPasswordEncoder(); 27 } 28 29 @Override 30 protected void configure(HttpSecurity http) throws Exception { 31 http.authorizeRequests() 32 .antMatchers("/js/**", "/css/**").permitAll() 33 .antMatchers("/**").authenticated() 34 .and() 35 .formLogin() 36 .loginPage("/loginForm") 37 .loginProcessingUrl("/login") 38 .usernameParameter("username") 39 .passwordParameter("password") 40 .defaultSuccessUrl("/rooms", true) 41 .failureUrl("/loginForm?error=true").permitAll(); 42 } 43 44 @Override 45 protected void configure(AuthenticationManagerBuilder auth) throws Exception { 46 //指定のUserDetailsServiceとPasswordEncoderを使用して認証を行う 47 auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder()); 48 } 49} 50
試したこと
ReservationUserDetailsServiceクラスにて、ユーザーをDBからの取得していることは確認できました。おそらくWebSecurityConfigの設定の仕方に問題がありログインが出来ないのだと思われます。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。