1. 使用security进行用户校验,首先要实现UserDetailsService接口,用于获取用户信息进行校验;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
log.info("输入的用户名是:" + username);
UserModel user = new UserModel();
user.setUserName(username);
user.setAge(18);
user.setPassword("123456");
log.info("通过业务逻辑得到的用户信息为:" + JSONObject.toJSONString(user));
String authorityList = "admin,user,root";
UserDetails userDetail = new User(user.getUserName(), user.getPassword(), AuthorityUtils.commaSeparatedStringToAuthorityList(authorityList));
return userDetail;
}
2. 在执行的时候,发现出现了以下问题:
java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"
网上百度了一下发现这是由于Spring security5中新增加了加密方式,并把原有的spring security的密码存储格式改了。
去官网查找得知,修改后的密码存储格式为:{id}encodedPassword
我们只需要对前端传过来的密码进行某种方式加密,就可以了,而官方推荐的是使用bcrypt的加密方式。
解决办法如下:在Securty配置类SecurtyConfig(继承 WebSecurityConfigurerAdapter)中修改 配置即可。
简单起见,还有一个也可以解决,使用过期的方法:
@Bean
public static PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
之后就看到了正确的结果,当我们输入的密码不是上面指定的“123456”时会报出“坏的凭证”,否则正确执行得到结果。
3. 如果除了严重密码是否正确外,还需要验证用户的其他信息,比如:账号过期、账号锁定、密码过期、账号被删除(逻辑删除或冻结)等,可以修改返回的用户详细信息。
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
log.info("输入的用户名是:" + username);
UserModel user = new UserModel();
user.setUserName(username);
user.setAge(18);
user.setPassword("123456");
user.setAccountNonExpired(false); //账号没有过期
user.setAccountNonLocked(true); //账号没有锁定
user.setCredentialsNonExpired(true); //密码没有过期
user.setEnabled(true); //账号是否可用(没有被删除)
log.info("通过业务逻辑得到的用户信息为:" + JSONObject.toJSONString(user));
String authorityList = "admin,user,root";
// UserDetails userDetail = new User(user.getUserName(), user.getPassword(), AuthorityUtils.commaSeparatedStringToAuthorityList(authorityList));
UserDetails userDetail = new User(user.getUserName(), user.getPassword(),
user.isEnabled(), user.isAccountNonExpired(), user.isCredentialsNonExpired(), user.isAccountNonLocked(),
AuthorityUtils.commaSeparatedStringToAuthorityList(authorityList));
return userDetail;
}
4. 密码加密解密方式:
首先定义加密方式:
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
然后,可以读取业务逻辑中保存的加过密的密码,这里也可以直接使用加密我们密码的方式来得到密文:
//加过密的密码
String encoderPassword = passwordEncoder.encode(user.getPassword());
最后,在返回的用户详细信息中使用这个加过密的密文即可:
log.info("加密后的密码为:" + encoderPassword);
UserDetails userDetail = new User(user.getUserName(), encoderPassword,
user.isEnabled(), user.isAccountNonExpired(), user.isCredentialsNonExpired(), user.isAccountNonLocked(),
AuthorityUtils.commaSeparatedStringToAuthorityList(authorityList));
return userDetail;
另外,说明一点是:用BCryptPasswordEncoder执行过加密的密文,每次结果是不一样的,是加过盐的。