登录 Spring 安全重定向到错误 Thymeleaf 和基于 Java 的配置
Posted
技术标签:
【中文标题】登录 Spring 安全重定向到错误 Thymeleaf 和基于 Java 的配置【英文标题】:Login in Spring security redirects to error Thymeleaf and Java based Configuration 【发布时间】:2019-07-17 14:34:06 【问题描述】:我正在尝试在我的 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]
【问题讨论】:
删除 .anyRequest().authenticated() 看看你是否登录成功。然后将其放在角色 antMatchers 之后。 已经试过了,没有运气! 那一定是一些愚蠢的错字/错误配置。我们需要更多信息。请将logging.level.org.springframework.security = DEBUG
添加到您的应用程序属性中,并将日志包含在您的问题中。
哦。我刚刚注意到您急切地加载角色,这意味着它是在在密码检查发生之前加载的。因此,您也可能在数据库中存储了无效的凭据。您确定密码已正确编码存储在数据库中吗?
我已经更新了 logging.level.org.springframework.security = DEBUG 添加到我的 application.properties 文件
【参考方案1】:
尝试删除此方法:
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception
auth.userDetailsService(userDetailsService)
.passwordEncoder(bCryptPasswordEncoder);
Spring Boot 自动选择 UserDetailsService
和 PasswordEncoder
bean。如果您覆盖此方法,它会使用完全不同的方式来创建 AuthenticationManager
【讨论】:
我删除了覆盖,没有什么不同...我在第二次编辑时添加了休眠日志 您的测试用户是否在数据库中设置了任何角色?我记不太清楚了,但我认为在 Spring Security 的某个地方有一个断言,即用户必须至少有一个身份验证。 我自己在数据库中的角色表中添加了 role_id 和角色以上是关于登录 Spring 安全重定向到错误 Thymeleaf 和基于 Java 的配置的主要内容,如果未能解决你的问题,请参考以下文章
Spring 安全性和 Angular javascript 重定向到登录页面
会话超时后,Spring 安全性不会重定向到上次请求的页面登录
使用Spring Social,Spring安全登录后重定向到原始URL?