在上文中,每次登陆的密码都是由系统随机生成的,这不符合实际应用,用户输入账号密码后应从数据库或其他存储中查找是否匹配。

在SpringSecurity中,通过实现UserDetailsService接口的loadUserByUsername()方法来完成用户登录的自定义验证。

下面首先是自定义用户身份校验逻辑:

SpringSecurity学习之路6-自定义用户认证逻辑

loadUserByUsername()方法的返回值类型是UserDetails,返回值User是security提供的实现了UserDetails接口的系统类。以上面这个为例,它代表着存在一个用户名为username、密码为123456且具有admin权限的用户。现在就是写死了,只有当用户输入的密码为123456时才能登陆系统。在用户登录时,系统会根据在这里得到的返回值来跟用户输入的信息做匹配。

除了上述的可以根据用户名加密码的方式来判断用户登录成功与否,还可以判断用户的状态(冻结、密码失效),根据判断的结果作为登录成功与否的依据。下面是User类的部分源码:

SpringSecurity学习之路6-自定义用户认证逻辑

举个例子,把密码为123456的账户锁定,代码如下:

SpringSecurity学习之路6-自定义用户认证逻辑

此时再在浏览器中输入用户名和密码后,就会出现以下提示:

SpringSecurity学习之路6-自定义用户认证逻辑

账号锁定状态与账号是否启用的区别,锁定:会解锁,还可能能用。是否启用:用户注销账号,或被永久封停,该账户已失效不可用。

实际操作中要比这复杂,你可以自定义用户账户是否被锁定等。

 

可以看到,以上的密码信息都是明文,我们也许应该在用户注册时就将用户的密码加密存储在数据库之中。当用户登录时,系统会根据加密规则反向解密跟用户输入的密码做匹配。在下面的代码中用到了PasswordEncoder类,查看源码发现这个类是一个接口类,用来实现加密的BCryptPasswordEncoder实现了这个接口,也就是说我们可以自定义实现PasswordEncoder的加密实现类来完成加密。

SpringSecurity学习之路6-自定义用户认证逻辑

SpringSecurity学习之路6-自定义用户认证逻辑

 

在PasswordEncoder接口中有两个方法,如下:

SpringSecurity学习之路6-自定义用户认证逻辑

matches()方法不需要我们自己调用。下面是我使用BCryptPasswordEncoder加密方式,以密码123456登录两次日志打印的信息:

SpringSecurity学习之路6-自定义用户认证逻辑

可以看到,123456被同一种加密方式加密两次,却得到了截然不同的结果,这正是PasswordEncoder的强大之处,即使有两个用户注册时使用了相同的密码,存储到数据库中的密码也不会相同,即使某人的密码泄露,也不会危及到其他人密码信息安全。在这里,使用到了 盐 ,把这个盐放进加密生成的字符串之中,就是最终存储在数据库中的密码。用户登录时,调用matches()方法,得到用户输入的密码密文,加上盐得到最终密文密码,与数据库中查找到的密文密码匹配。

至此,关于用户信息处理逻辑和密码加密的介绍结束。

 

 

相关文章: