目录
前言
文章之后补全spring-security登录时用户认证进行密码加密验证和实现记住我功能。
一、用户登录密码加密认证
1. 修改上一篇文章中的项目wqdemotwo的spring-security.xml配置文件
打开如下标红的两处配置:
什么意思呢?
<bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"></bean> 是在配置文件中声明一个bean,实现BCryptPasswordEncoder类。
<security:password-encoder ref="passwordEncoder"/> 是将声明的bean “passwordEncoder” 注入到 authentication-provider 中去。对应的 AuthenticationProvider 类是认证提供者。此处指定了myUserDetailsService 服务类(获取用户详情,如 用户名,密码等)
2. 生成加密后的密码,实现登录认证
进入加密算法实现类:BCryptPasswordEncoder
进入接口:PasswordEncoder
encode()方法对明文密码进行加密。我们调用这个方法对数据库中的密码进行加密:
此处我随意找一个类生成加密密码:就 LoginController 类吧
运行项目生成加密密码:$2a$10$n/q4O15Lg9d1WvelfRu9i.qrgE5iVjTeD4.hXAqsLZaGRmTKoGxtK录入到数据库中。
完成,现在重新启动项目查看登录效果:用户:zhangsan,密码:123456
系统登录成功:
执行loadUserByUsername查询用户详情方法后,后台打印结果,密码加密了。
3. 补充说明
总结一下:整个登录认证过程中我们并没有做密码的对比校验,但是密码输入错误是无法登录认证成功的。这是因为密码比对交由 SpringSecurity 处理了,登录页面传入 用户名 通过详情查询方法loadUserByUsername 获取了UserDetails(得到了数据库中的用户名和密码)然后返回给了SpringSecurity 进行密码校验。
spring-security.xml 配置文件中注入了AuthenticationManager 身份验证管理器类,AuthenticationProvider认证提供者类,PasswordEncoder接口的实现类等。执行时会执行一系列相关类(源码就不研究了,有情怀的小伙伴可以试试)。最终完成用户登录认证。而 密码的校验是由BCryptPasswordEncoder类 通过实现PasswordEncoder接口 的matches方法来完成。
我们可以来验证一下。将数据库中用户zhangsan的密码改回明文123456。此时运行项目进行登录,结果是登录失败了:
后台打印数据库获取的密码是123456明文,小伙伴注意到下图最后一行的红字。
BCryptPasswordEncoder.matches Encoded password does not look like BCrypt:什么意思呢?就是BCryptPasswordEncode类的matches方法中报出了 密码不属于自己(BCrypt)的编码格式,下图:
matches方法中如果通过了编码格式校验则进入checkpw(rawPassword.toString(), encodedPassword)方法,rawPassword登录页面传入的,encodedPassword数据库中存储的。所以密码的校验是由BCryptPasswordEncoder类 通过实现PasswordEncoder接口 的matches方法来完成。
二、记住我功能
1. 将上篇文章项目wqdemotwo的spring-security.xml配置文件,打开如下两处配置
说明:token-validity-seconds="300" 属性指定免登录访问资源的维持时间,超过这个时间没有任何资源请求,便需要重新登录。
及
注意:第一次运行项目时要将<!--<property name="createTableOnStartup" value="true"/>--> 配置打开,createTableOnStartup属性是当项目启动时,springSecurity创建表存储remember me相关信息,第二次启动时要注释这个属性。
说明:<property name="dataSource" ref="dataSource"/>指定数据库数据源,如oracle。ref="dataSource"注入的是applicationContext.xml配置文件中的数据源,如下图:
2. 修改登录页面
增加 记住我 复选框,如图:
到此记住我功能配置完成,打开spring-security.xml文件的createTableOnStartup属性运行项目,按预期设想应该在数据库生成表PERSISTENT_LOGINS:
-- Create table
create table PERSISTENT_LOGINS
(
username VARCHAR2(64) not null,
series VARCHAR2(64) not null,
token VARCHAR2(64) not null,
last_used TIMESTAMP(6) not null
);
-- Create/Recreate primary, unique and foreign key constraints
alter table PERSISTENT_LOGINS
add primary key (SERIES)
登录页面选择 记住我 登录成功后,关闭浏览器可以实现免登录再次访问资源。
选择 记住我 进行登录,成功登录了。此时我打开oracle数据库生成了PERSISTENT_LOGINS表
页面也成功访问到资源:
此时关闭浏览器,再次打开浏览器因该可以不用登录就可以直接访问主页面。但是我的想法是美好的,事实却是访问 http://localhost:8080/wqdemotwo_war/system/index 跳转到了登录页面,经过努力查找原因是:spring-security.xml文件的 <security:intercept-url pattern="/**" access="isFullyAuthenticated()"/> 配置导致,需要改成 <security:intercept-url pattern="/**" access="isAuthenticated()"/> 这个。
isAuthenticated():Returns true if the user is not anonymous(如果用户不是匿名的,则返回true)
isFullyAuthenticated(): Returns true if the user is not an anonymous or a remember-me user(如果用户不是匿名用户或记住我的用户,则返回true)
修改后再次运行项目,便可以实现 记住我 功能,即:登录成功后关闭浏览器,再次打开浏览器访问资源可以免登录访问。(记住注释掉spring-security.xml文件的<!--<property name="createTableOnStartup" value="true"/>-->属性)
好了,今天的记录到此结束。