我正在尝试在Spring应用程序上实现基于角色的身份验证。但是,即使凭据正确,我也会被重定向到http://localhost:8080/login?error=true,并且hibernate可以毫无问题地获取登录凭据。
这是我的SecurityConfig类
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
private static final String[] PUBLIC_MATCHERS = {
"/css/**","/js/**","/image/**","/fonts/**","/webfonts/**","/register","/login","/actuator/**"
};
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers(PUBLIC_MATCHERS).permitAll().anyRequest().authenticated()
.antMatchers("/addShipping").hasAuthority("ROLE_USER")
.antMatchers("/item/add").hasAuthority("ROLE_ADMIN")
.and().formLogin().loginPage("/login").failureUrl("/login?error=true").defaultSuccessUrl("/",true)
.and()
.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/")
.deleteCookies("remember-me")
.permitAll()
.and().rememberMe()
.and().exceptionHandling().accessDeniedPage("/denied");
}
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(bCryptPasswordEncoder);
}
这是我的登录控制器
@RequestMapping(value = "/login", method = RequestMethod.GET)
public String login(Model model) {
return "login";
}
我的角色课程
@Data
@Entity
public class Role {
@Id
@Column(name="role_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotNull
@Column(name ="role")
private String role;
}
用户类别
@Entity
@Data
public class User implements UserDetails {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name ="user_id")
private Long id;
@OneToOne(cascade = CascadeType.ALL)
private Cart cart;
@OneToMany(mappedBy = "user")
private List<Order> order;
@NotEmpty(message="username is required")
private String username;
@NotEmpty(message="password is required")
private String password;
@NotEmpty(message="password is required")
private String fullname;
private int enabled;
@NotBlank(message="Pleace Provide your Role")
private String role;
@NotEmpty
@Email
private String email;
@NotEmpty(message="phone is required")
private String phone;
@ManyToMany(cascade = CascadeType.ALL, fetch=FetchType.EAGER)
@JoinTable( name="user_role",
joinColumns= {@JoinColumn(name="user_id")},
inverseJoinColumns= {@JoinColumn(name="role_id")})
private Set<Role> roles;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Set<GrantedAuthority> authorities = roles
.stream()
.map(role -> new SimpleGrantedAuthority(role.getRole()))
.collect(Collectors.toSet());
return authorities;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
登录模板
<div th:if="${param.error != null}" style="color: red;">Incorrect credentials</div>
<form th:action="@{/login}" method="post">
<div class="form-group"><input required="required" type="text" class="form-control" id="username" name="username" placeholder="Username" /></div>
<div class="form-group"> <input required="required" type="password" class="form-control" id="password" name="password" placeholder="Password" /></div>
<div class="col-sm-6 col-sm-offset-3 text-center">
<input type="checkbox" class="" name="remember" id="remember">
<label for="remember"> Remember Me</label>
</div>
<div class="col-sm-6 col-sm-offset-3"> <button type="submit" class="btn btn-primary btn-block">Log in</button> </div>
</form>
[编辑]
用户服务
public interface UserService extends UserDetailsService {
void save(User user);
User findUserByUsername(String username);
}
用户服务实施
@Service
public class UserServicelmpl implements UserService {
private BCryptPasswordEncoder bCryptPasswordEncoder;
private UserRepository userRepository;
private RoleRepository roleRepository;
@Autowired
public UserServicelmpl(UserRepository userRepository, RoleRepository
roleRepository, BCryptPasswordEncoder bCryptPasswordEncoder) {
this.userRepository = userRepository;
this.roleRepository = roleRepository;
this.bCryptPasswordEncoder = bCryptPasswordEncoder;
}
@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if (user != null) {
return user;
}
throw new UsernameNotFoundException("The user with user name of '" +
username + "' is not found");
}
@Override
public void save(User user) {
user.setPassword(bCryptPasswordEncoder.encode(user.getPassword()));
user.setEnabled(true);
String Role = "ROLE_"+ user.getRole();
Role userRole = roleRepository.findByRole(Role);
user.setRoles(new HashSet<Role>(Arrays.asList(userRole)));
userRepository.save(user);
}
@Override
public User findUserByUsername(String username) {
return userRepository.findByUsername(username);
}
}
[编辑2] 日志
o.s.s.a.dao.DaoAuthenticationProvider:身份验证失败:密码与存储的值不匹配
w.a.UsernamePasswordAuthenticationFilter:身份验证请求失败:org.springframework.security.authentication.BadCredentialsException:错误的凭据
org.springframework.security.authentication.BadCredentialsException:错误的凭证 在org.springframework.security.authentication.dao.DaoAuthenticationProvider.additionalAuthenticationChecks(DaoAuthenticationProvider.java:93)〜[spring-security-core-5.1.2.RELEASE.jar:5.1.2.RELEASE] 在org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:166)〜[spring-security-core-5.1.2.RELEASE.jar:5.1.2.RELEASE]
答案 0 :(得分:0)
尝试删除此方法:
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(bCryptPasswordEncoder);
}
Spring Boot自动选择UserDetailsService
和PasswordEncoder
bean。如果您覆盖此方法,则它会使用完全不同的方式来创建AuthenticationManager