3.自定义用户认证逻辑
我们系统默认登录的用户名默认是:user;而对应的密码是每次服务启动后随机生成的密码。常见的场景是我们的用户应该是从数据库读取的。我们从下面几个方面述说自定义用户认证逻辑。
- 处理用户信息获取逻辑(从数据库获取) <-----> UserDetailsService
- 处理用户校验逻辑 <-----> UserDetails
- 处理密码加密解密 <-----> PasswordEncoder
3.1 处理用户信息获取逻辑(从数据库获取)
用户信息获取逻辑是封装到spring-security里面的UserDetailsService里面有:loadUserByUsername方法
@Component
public class MyUserDetailsService implements UserDetailsService {
private Logger logger \= LoggerFactory.getLogger(getClass());
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//返回一个实例对象,我们使用spring-security自带的User
logger.info("登录用户名:"+username);
//根据用户名密码查询授权
return new User(username,"123456", AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
}
}
web端测试:
错误用户名/密码:
正确用户名/密码:
3.2 处理用户校验逻辑
用户校验分为两部分:
- 密码是否匹配,你只要告诉Spring-Security的密码是多少就可以了。
- 其他校验:用户是不是被冻结了。是不是密码过期了。
我们在loadUserByUsername里面返回的是:UserDetails,注意UserDetails
public interface UserDetails extends Serializable {
Collection<? extends GrantedAuthority> getAuthorities();
String getPassword();
String getUsername();
boolean isAccountNonExpired(); //账号是不是过期了
boolean isAccountNonLocked(); //账户是不是锁定了
boolean isCredentialsNonExpired(); //密码是否过期了
boolean isEnabled(); //用户是不是被假删除了
}
其中7个参数的构造函数:多了4个方法判断结果;
@Component
public class MyUserDetailsService implements UserDetailsService {
private Logger logger = LoggerFactory.getLogger(getClass());
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//返回一个实例对象,我们使用spring-security自带的User
logger.info("登录用户名:"+username);
//根据用户名查找用户信息
//根据查找到的用户信息判断用户是否被冻结:我们用7个参数的构造方法
// new User(username,"123456", AuthorityUtils.commaSeparatedStringToAuthorityList("admin"))
//创建一个用户被锁定账号
UserDetails user = new User(username,"123456", true,true,
true,false, AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
return user;
}
}
前端访问:用户名/密码:Jack/123456
请求的结果为:
因为我们把构造器的参数:accountNonLocked设置为false
我们改为true即可登录。
3.3 处理密码加密解密
在我们的应用中,不会使用明文的密码保存到数据库,从数据库里面取出来的东西也不是明文的,Spring-security中密码加密解密的是一个新的接口。叫做:PasswordEncoder
//对用户信息进行编码;供用户来调用
String encode(CharSequence var1);
//数据库里面代码是否跟传过来的代码匹配
boolean matches(CharSequence var1, String var2);
我们在WebSecurityConfig配置一个PasswordEncoder类:
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
/**
* 定义web安全配置类:覆盖config方法
* 1.参数为HttpSecurity
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
/**
* 定义了任何请求都需要表单认证
*/
http.formLogin()//表单登录---指定了身份认证方式
// http.httpBasic()//http的basic登录
.and()
.authorizeRequests()//对请求进行授权
.anyRequest()//任何请求
.authenticated();//都需要认证
}
}
然后我们请求接口:发现报错,原因是我们返回的User的密码是明文的
MyUserDetailsService修改:
@Component
public class MyUserDetailsService implements UserDetailsService {
private Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//返回一个实例对象,我们使用spring-security自带的User
logger.info("登录用户名:"+username);
//根据用户名查找用户信息
//根据查找到的用户信息判断用户是否被冻结:我们用7个参数的构造方法
// new User(username,"123456", AuthorityUtils.commaSeparatedStringToAuthorityList("admin"))
//创建一个用户被锁定账号
UserDetails user = new User(username,passwordEncoder.encode("123456"), true,true,
true,true,
AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
return user;
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。