05 SpringSecurity-实现自动登录

本文介绍了Spring Security中的两种自动登录机制:散列加密方案和持久化令牌方案。散列加密方案通过散列算法生成自动登录令牌,而持久化令牌方案则采用更严格的安全设计,利用系列值和令牌值来确保安全性。

文章配套代码:https://gitee.com/lookoutthebush/spring-security-demo

自动登录是将用户的登录信息保存在用户浏览器的cookie中,当用户下次访问时,自动实现校验 并建立登录态的一种机制。

Spring Security提供了两种非常好的令牌:

  • 用散列算法加密用户必要的登录信息并生成令牌。
  • 数据库等持久性数据存储机制用的持久化令牌。

散列算法在Spring Security中是通过加密几个关键信息实现的:

hashInfo = md5Hex(username + ":" + expirationTime + ":" + password + ":" + key)
rememberCookie = base64(username + ":" + expirationTime + ":" + hashInfo)

其中,expirationTime指本次自动登录的有效期,key为指定的一个散列盐值,用于防止令牌被修 改。通过这种方式生成cookie后,在下次登录时,SpringSecurity首先用Base64简单解码得到用户名、 过期时间和加密散列值;然后使用用户名得到密码;接着重新以该散列算法正向计算,并将计算结果与旧的加密散列值进行对比,从而确认该令牌是否有效。

一、散列加密方案

1、修改配置

 1、rememberMeCookieName设置的是生成的cookie的名字

2、rememberMeParameter设置的是前端登录是传参的名字,如下图,SpringSecurity会使用这个名字取前端的参数

 3、key是一个散列盐值,没有指定的时候是一个随机的UUID字符串,这样每次启动服务,或者部署多台机器都会导致自动登录使用的cookie失效。所以直接指定一个固定的。

4、userDetailService需要指定,用来查询用户信息进行对比

2.前端代码修改

            <div class="layui-form-item">
              <div class="layui-input-inline">
                <input type="checkbox" name="remember" title="记住我" >
              </div>
              <div class="layui-form-mid" style="float: right">
                <a href="#" class="wait" style="color: #777777">忘记密码</a>
              </div>
            </div>

具体可以查看开头的demo源码

3.启动服务

 登录后,查看cookie,会发现有了一个uc-token。

 之前每次重启项目都需要重新登录,现在重新启动服务,发现不需要登录了。

二、持久化令牌方案

持久化令牌方案在交互上与散列加密方案一致,都是在用户勾选Remember-me之后,将生成的令 牌发送到用户浏览器,并在用户下次访问系统时读取该令牌进行认证。不同的是,它采用了更加严谨 的安全性设计。

在持久化令牌方案中,最核心的是series和token两个值,它们都是用MD5散列过的随机字符串。 不同的是,series仅在用户使用密码重新登录时更新,而token会在每一个新的session中都重新生成。

这样设计有什么好处呢?

首先,解决了散列加密方案中一个令牌可以同时在多端登录的问题。持久化方案每个会话都会引发token的更 新,即每个token仅支持单实例登录。

其次,自动登录不会导致series变更,而每次自动登录都需要同时验证series和token两个值,当该 令牌还未使用过自动登录就被盗取时,系统会在非法用户验证通过后刷新 token 值,此时在合法用户的浏览器中,该token值已经失效。当合法用户使用自动登录时,由于该series对应的 token 不同,系统 可以推断该令牌可能已被盗用,从而做一些处理。例如,清理该用户的所有自动登录令牌,并通知该用户可能已被盗号等。

1.数据库表

SpringSecurity相关的代码逻辑已经实现了,对应的实体:

public class PersistentRememberMeToken {

	private final String username;

	private final String series;

	private final String tokenValue;

	private final Date date;

	public PersistentRememberMeToken(String username, String series, String tokenValue, Date date) {
		this.username = username;
		this.series = series;
		this.tokenValue = tokenValue;
		this.date = date;
	}

	public String getUsername() {
		return this.username;
	}

	public String getSeries() {
		return this.series;
	}

	public String getTokenValue() {
		return this.tokenValue;
	}

	public Date getDate() {
		return this.date;
	}

}

因此我们需要按照实体,创建一个数据库表:

数据库sql也有提供:

public class JdbcTokenRepositoryImpl extends JdbcDaoSupport implements PersistentTokenRepository {

	/** Default SQL for creating the database table to store the tokens */
	public static final String CREATE_TABLE_SQL = "create table persistent_logins (username varchar(64) not null, series varchar(64) primary key, "
			+ "token varchar(64) not null, last_used timestamp not null)";

这里做了一些小改动,也可以按原样:

-- ---------------
-- 自动登录
-- ---------------
CREATE TABLE `persistent_logins` (
    `series` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '主键',
    `username` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '用户名',
    `token` VARCHAR(64) NOT NULL DEFAULT '' COMMENT 'token',
    `last_used` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '最后使用时间',
    PRIMARY KEY (`series`)
)ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT ='用户表';

表的主键是series,Spring Security可以通过series查询表中的其他信息。有了存储自动登录信息的表 之后,就可以继续配置Spring Security的Remember-me功能了。由于需要使用持久化令牌方案,所以指定tokenRepository。

2.修改配置类

仍然直接使用SpringSecurity提供的。

3.运行

输入账号密码登录成功后,查看数据库,会有一条数据产生。

 重启项目等都不需要再次登录。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七号公园的忧伤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值