Я пытаюсь реализовать аутентификацию на основе ролей в моем приложении 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] Журнал
ossadao.DaoAuthenticationProvider: аутентификация не пройдена: пароль не соответствует сохраненному значению
waUsernamePasswordAuthenticationFilter: сбой запроса аутентификации: org.springframework.security.authentication.BadCredentialsException: неверные учетные данные
* 10secf..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-security5.1.2.RELEASE.jar: 5.1.2.RELEASE]