java - Spring Security - 即使凭据良好,登录也会失败
问题描述
我对 spring 和 spring security 有点陌生。我一直在尝试使用 Spring Security 实现具有身份验证/授权的基本登录,我一直在关注网络上的几个教程,但没有一个真正帮助我。当我尝试使用数据库中的用户登录时,它给了我错误:凭据错误
这是我使用的代码:用户/角色/权限实体
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "user_id")
private int id;
private String name;
private String email;
private String password;
private String usual_IP;
private int logged;
@ManyToMany
@JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
private List<Role> roles;
角色
@Entity
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "role_id")
private int id;
private String name;
private String description;
@ManyToMany(mappedBy = "roles")
@JsonIgnore
private List<User> users;
特权
@Entity
public class Privilege {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "Privilege_id")
private int id;
private String name;
@ManyToMany(mappedBy = "privileges")
private List<Role> roles;
这是弹簧配置
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsServiceImpl userDetailsService;
@Autowired
private DataSource dataSource;
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.
userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.
authorizeRequests()
.antMatchers("/", "/login", "/logout").permitAll()
.antMatchers("/users").permitAll()
.antMatchers("/user/").permitAll()
.antMatchers("/user/**").permitAll()
.antMatchers("/users/**").permitAll()
.antMatchers("/roles").permitAll()
.antMatchers("/role").permitAll()
.antMatchers("/role/**").permitAll()
.antMatchers("/userInfo").access("hasAnyRole('USER', 'ADMIN')")
.antMatchers("/admin").access("hasRole('ADMIN')")
.anyRequest().authenticated().and().csrf().disable().formLogin()
.and().exceptionHandling().accessDeniedPage("/403")
.and().formLogin()//
.loginProcessingUrl("/j_spring_security_check")
.loginPage("/login")//
.defaultSuccessUrl("/userAccountInfo")//
.failureUrl("/login?error=true")//
.usernameParameter("name")//
.passwordParameter("password")
.and().logout().logoutUrl("/logout").logoutSuccessUrl("/logoutSuccessful")
.and().exceptionHandling();
}
这里是 usersDetailsService 的实现
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
@Transactional
public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException {
User user = userRepository.findByName(name);
if(user==null) {throw new UsernameNotFoundException("No such user: " + name);
} else if (user.getRoles().isEmpty()) {
throw new UsernameNotFoundException("User " + name + " has no authorities");
}
UserDetailsAdapter userToAdapt = new UserDetailsAdapter(user);
return userToAdapt;
}
}
userDetails 实现
public class UserDetailsAdapter implements UserDetails {
private User user;
public UserDetailsAdapter(User user) {this.user = user;}
public User getAccount() {return user;}
public Integer getId(){return user.getId();}
public String getEmail () {return user.getEmail();}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<GrantedAuthority> authorities= new ArrayList<>();
for (Role role: user.getRoles()) {
authorities.add(new SimpleGrantedAuthority(role.getName()));
role.getPrivileges().stream().map(p -> new SimpleGrantedAuthority(p.getName())).forEach(authorities::add);
}
return authorities;
}
@Override
public String getPassword() {
return user.getPassword();
}
@Override
public String getUsername() {
return user.getName();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
登录控制器
@RequestMapping(value = "/login", method = RequestMethod.GET)
public String loginPage(Model model) {
return "loginPage";
}
@RequestMapping(value = "/userInfo", method = RequestMethod.GET)
public String userInfo(Model model, User user) {
// After user login successfully.
String userName = user.getName();
System.out.println("User Name: " + userName);
User loginedUser = user;
String userInfo = user.toString();
model.addAttribute("userInfo", userInfo);
return "userInfoPage";
}
还有百里香模板
<!-- /login?error=true -->
<div th:if="${#request.getParameter('error') == 'true'}"
style="color:red;margin:10px 0px;">
Login Failed!!!<br />
Reason :
<span th:if="${#session!= null and
#session.getAttribute('SPRING_SECURITY_LAST_EXCEPTION') != null}"
th:utext="${#session.getAttribute
('SPRING_SECURITY_LAST_EXCEPTION').message}">
Static summary
</span>
</div>
<h3>Enter user name and password:</h3>
<form name='f' th:action="@{/j_spring_security_check}" method='POST'>
<table>
<tr>
<td>User:</td>
<td><input type='text' name='name' value=''></td>
</tr>
<tr>
<td>Password:</td>
<td><input type='password' name='password' /></td>
</tr>
<tr>
<td>Remember Me?</td>
<td><input type="checkbox" name="remember-me" /></td>
</tr>
<tr>
<td><input name="submit" type="submit" value="submit" /></td>
</tr>
</table>
</form>
编辑
这是将用户保存到数据库中并对密码进行编码的服务
@Override
public void saveUser(User user) {
user.setPassword(bCryptPasswordEncoder.encode(user.getPassword()));
userRepository.save(user);
}
这是我用来通过邮递员手动将新用户添加到数据库中的控制器
@RequestMapping(value = "/users", method = RequestMethod.POST)
public ResponseEntity<Void> createUser(@RequestBody User user, UriComponentsBuilder ucBuilder) {
if (userServices.isUserExist(user)) {
return new ResponseEntity(new CustomErrorType("Unable to create. A User with name " +
user.getName() + " already exist."),HttpStatus.CONFLICT);
}
userServices.saveUser(user);
HttpHeaders headers = new HttpHeaders();
headers.setLocation(ucBuilder.path("/api/user/{id}").buildAndExpand(user.getId()).toUri());
return new ResponseEntity<>(headers, HttpStatus.CREATED);
}
有人可以帮忙,我无法查明错误,非常感谢
解决方案
我找到了问题的答案,我对密码进行了两次编码,因此当他们比较两个密码时,他们从未匹配过。感谢所有帮助过的人
推荐阅读
- git - 如何在不丢失原始哈希码和我应该提交的代码的情况下恢复 git commit --amend -m?
- python - 我在以下程序中遇到错误,因为 KeyError Traceback(最近一次调用最后一次)
- javascript - Next.js 刷新页面中断 css classNames
- python-3.x - Microsoft MSAL Resource Owner Password Credentials(ROPC) Grant 授权是否支持 ClientConfidentialApplicaton 类获取 Token?
- javascript - 为什么 setState 会导致我的 React 应用程序进入无限循环?
- peoplesoft - 是否有一个列表或方法来查找所有具有不同名称但包含相同数据的字段?
- python - 当我使用 selenium 时,我得到“StaleElementReferenceException: stale element reference: element is not attach to the page document”
- windows - 如何在 Visual Studio 等 VS Code 中进行块粘贴
- python - Geopandas - read_file() 函数通过共享网络非常慢。如何在不通过共享网络读取文件的情况下运行应用程序
- html - 当显示大小发生变化时,如何正确调整社交媒体图标的大小?