其实用户登录拦截的这块不想这么早写,加个登录后面好多东西就要考虑登录状态了,我其实想把这个系列写成非必要关系,解耦性比较强
的系列。但是,写完redis,总是感觉登录是对它最简单的实践,那就加上吧,反正后面很多文章也会用到,但大多文章我仍会不考虑登录状态。
这里只是讲明白登录机制,如何实现。实际使用中会考虑很多别的,例如用户权限,登录机制限制等等~这里就先不做过多的叙述。
这里只讲技术和实现,不讲任何业务场景哈,牵扯到场景的问题就会复杂N倍,而且通用性往往不尽人意~
本文依赖于redis和mybatis plus,这些都是最基础的模块,所以都放在最前面写了,大家可以线过一下相关的文章。
【笑小枫的SpringBoot系列】【八】SpringBoot集成Redis
【笑小枫的SpringBoot系列】【三】SpringBoot集成Mybatis Plus
本文是基于jwt+redis来实现。接下来我们一起看看吧
什么是JWT
什么是JWT,JWT(全称:Json Web Token)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。 该信息可以被验证和信任,因为它是数字签名的。
上面说法比较文绉绉,简单点说就是一种认证机制,让后台知道该请求是来自于受信的客户端。
JWT的优点
- json格式的通用性,所以JWT可以跨语言支持,比如Java、JavaScript、PHP、Node等等。
- 可以利用Payload存储一些非敏感的信息。
- 便于传输,JWT结构简单,字节占用小。
- 不需要在服务端保存会话信息,易于应用的扩展。
JWT的缺点
- 安全性没法保证,所以jwt里不能存储敏感数据。因为jwt的payload并没有加密,只是用Base64编码而已。
- 无法中途废弃。因为一旦签发了一个jwt,在到期之前始终都是有效的,如果用户信息发生更新了,只能等旧的jwt过期后重新签发新的jwt。
- 续签问题。当签发的jwt保存在客户端,客户端一直在操作页面,按道理应该一直为客户端续长有效时间,否则当jwt有效期到了就会导致用户需要重新登录。
补偿JWT的缺点
- 针对JWT的缺点,我们在使用的过程中,只储存常用的无敏感数据,比如用户ID,用户角色等。
- 中途废弃和续签问题,通过和redis配合使用,将token返回时,同步保存redis,通过控制token在redis的有效期来进行控制。
- 还可以通过统计redis有效数据,对在线用户进行统计或强制下线等操作。
用户登录流程
以用户登录功能为例,程序流程如下:
用户登录
笑小枫-www.xiaoxiaofeng.site
token认证访问
笑小枫-www.xiaoxiaofeng.site
注:系统中采用JWT对用户登录授权验证。
基于Token的身份验证流程
使用基于Token的身份验证,在服务端不需要存储用户的登录记录。大概的流程是这样的:
1、客户端使用用户名或密码请求登录;
2、服务端收到请求,去验证用户名与密码;
3、验证成功后,服务端会使用JWT签发一个Token,保存到Redis中,同时再把这个Token发送给客户端;
4、客户端收到Token以后可以把它存储起来,比如放在Cookie里或者Local Storage里;
5、客户端每次向服务端请求资源的时候需要在请求Header里面带着服务端签发的Token;
6、服务端收到请求,然后去验证客户端请求里面带着的Token,如果验证成功,就向客户端返回请求的数据。验证失败,返回失败原因。
功能实现
自动生成的User.java
、UserMapper.java
、UserMapper.xml
...就不贴代码了,没有业务代码,且占的篇幅过大。在SpringBoot集成Mybatis Plus文章中创建过就可以忽略了哈~
代码生成见SpringBoot集成Mybatis Plus一文。
涉及到的表sql
在SpringBoot集成Mybatis Plus文章中创建过的就可以忽略了
CREATE TABLE `usc_user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
`account` varchar(30) DEFAULT NULL COMMENT '用户账号',
`user_name` varchar(30) DEFAULT NULL COMMENT '用户姓名',
`nick_name` varchar(30) DEFAULT NULL COMMENT '用户昵称',
`user_type` varchar(2) DEFAULT '00' COMMENT '用户类型(00系统用户,01小程序用户)',
`email` varchar(50) DEFAULT '' COMMENT '用户邮箱',
`phone` varchar(11) DEFAULT '' COMMENT '手机号码',
`sex` char(1) DEFAULT '0' COMMENT '用户性别(0男 1女 2未知)',
`avatar` varchar(100) DEFAULT '' COMMENT '头像地址',
`salt` varchar(32) DEFAULT NULL COMMENT '用户加密盐值',
`password` varchar(100) DEFAULT '' COMMENT '密码',
`status` char(1) DEFAULT '0' COMMENT '帐号状态(0正常 1停用)',
`create_id` bigint(20) DEFAULT NULL COMMENT '创建人id',
`create_name` varchar(64) DEFAULT '' COMMENT '创建者',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_id` bigint(20) DEFAULT NULL COMMENT '更新人id',
`update_name` varchar(64) DEFAULT '' COMMENT '更新者',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`delete_flag` tinyint(1) DEFAULT '0' COMMENT '删除标志',
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='用户中心-用户信息表';
引入依赖
首先我们在pom文件中引入依赖
<!-- 引入JWT相关 -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.18.3</version>
</dependency>
通用类
先把我们的通用类创建一下,一些常量,我们统一放在一个配置中,方便日后维护。
- 在config.bean创建通用类
GlobalConfig.java
package com.maple.demo.config.bean;
/**
* @author 笑小枫
* @date 2022