SpringBoot-登录校验
前言
通过JWT令牌
和Interceptor拦截器
实现登录校验功能(以一个简单的Demo实例演示)。
版本:
- Maven:3.6.1
- JDK:17
- SpringBoot:3.3.2
- API测试工具:Postman
项目实例构建
新建一个名为springboot_demo
的项目,并勾选添加如下依赖:
- Developer Tools
- Lombok
- Web
- Spring Web
- SQL
- MyBatis Framework
- MySQL Driver
项目目录如下:
POJO层:
User
类:
1
2
3
4
5
6
7
8
public class User {
private Integer id;
private String username;
private String password;
}
Result
类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Result {
private Integer code;
private String msg;
private Object data;
// 用于快速返回Result对象的三个静态方法
public static Result success(Object data) {
return new Result(1, "success", data);
}
public static Result success() {
return new Result(1, "success", null);
}
public static Result error(String msg) {
return new Result(0, msg, null);
}
}Mapper层:
UserMapper
接口:
1
2
3
4
5
6 //根据用户名和密码返回用户
public interface UserMapper {
User getUser(User user);
}Service层:
UserService
接口:
1
2
3 public interface UserService {
User login(User user);
}
UserServiceImpl
实现类:
1
2
3
4
5
6
7
8
9
10
11
public class UserServiceImpl implements UserService {
private UserMapper userMapper;
public User login(User user) {
return userMapper.getUser(user);
}
}
application.properties
配置数据库连接信息:
1 | springboot_demo = |
创建一个名为springboot_demo
的数据库,在其中新建一个user
表:
1 | SET NAMES utf8mb4; |
JWT令牌
简介
-
JWT:JSON Web Token(官网:JSON Web Tokens - jwt.io)
-
定义了一种简洁的、自包含的格式,用于在通信双方以json数据格式安全的传输信息。由于数字签名的存在,这些信息是可靠的。
-
应用场景:登录认证
- 浏览器向服务器发起登录请求
- 登录接口访问成功,服务器会生成一个JWT令牌,并返回给浏览器。
- 浏览器收到JWT令牌会将其存储起来(token),并在之后的每一次请求都携带该令牌。服务器在每次处理请求之前,都会先校验令牌。
不同于基于
Cookie
和基于Session
的会话跟踪技术,JWT令牌技术不需要服务器存储相应的令牌信息,并且该技术可以自定义设计有效时间,过期令牌作废。 -
组成:
- 第一部分:Header(头),记录令牌类型、签名算法等。例如:{“alg”:“HS256”,“type”:“JWT”}
- 第二部分:Payload(有效载荷),携带一些自定义信息、默认信息等。例如:{“id”:“1”,“username”:“Tom”}
- 第三部分:Signature(签名),防止Token被篡改、确保安全性。将header、payload加入指定密钥,通过指定的签名算法计算而来。
JWT生成&测试
在pom.xml
配置文件中引入JWT依赖:
1 | <!--JWT令牌--> |
生成
在测试目录下新建立一个测试生成方法testGenJwt()
:
1 |
|
通过
Jwts.builder()
方法构建一个JWT令牌,并通过如下方法设置参数:
signWith()
:设置签名算法和密钥(注意:密钥内容长度不得小于4个字符)setClaims()
:设置载荷部分,即自定义的数据(JSON格式),可以通过Map
集合进行封装setExpiration()
:设置令牌有效期(如果超出设置的有效期,那么令牌失效)调用
compact()
得到一个String类型的JWT令牌返回值。
测试结果:
1 | eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoidG9tIiwiaWQiOjEsImV4cCI6MTcyMzQzNzkxOX0.xSpMEChn44Nd41kuojWKs1cQD8v5gaWx-ar9Q_x7P3w |
可以将生成的结果输入至JWT官网查看:
解析
在测试目录下新建立一个测试解析方法testParseJwt()
:
1 |
|
通过
Jwts.parser()
方法解析JWT令牌,并通过如下方法设置参数:
setSigningKey()
:设置解析的签名密钥(必须同生成JWT令牌时设置的密钥一致)parseClaimsJws()
:传递被解析的JWT令牌调用
getBody()
:获取载荷部分(JWT令牌中设置的自定义内容)关于
Claims
类:Claims类是JWT(JSON Web Token)的一部分,用于存储和传输身份验证和授权信息。它包含了一组键值对,每个键值对都表示一个声明。声明是关于实体(通常是用户)和其他一些实体(如客户端、服务等)的声明性陈述。
1 import io.jsonwebtoken.Claims;
测试结果:
1 | {name=tom, id=1, exp=1723437919} |
如果JWT令牌解析校验时报错,则说明JWT令牌非法(被篡改或过期失效)。
Demo实例:登录后下发令牌
需求:如果登录请求成功,生成并返回JWT令牌;如果失败,返回错误信息。
创建utils.JwtUtils
工具类,方便快速生生成和解析使用:
1 | public class JwtUtils { |
创建controller.LoginController
类:
1 |
|
-
POST正确请求:
-
POST错误请求:
Interceptor拦截器
简介
- 概念:拦截器(Interceptor)是一种动态拦截方法调用的机制,类似于过滤器(Filter)。Interceptor是Spring框架中提供的,用于动态拦截控制器(Controller)方法的执行。
- 作用:拦截请求,在指定的方法调用前后,根据业务需要执行预先设定的代码。
Demo实例:拦截请求
需求:
-
正确发送登录请求,返回JWT令牌;否则返回错误信息。
要求请求头(Headers)中携带
token
字段,其值为JWT令牌。 -
携带正确JWT令牌发送其他请求,放行;否则返回错误信息。
首先创建interceptor.LoginCheckInterceptor
类,定义拦截器(实现HandlerInterceptor
接口,并重写其所有方法):
1 | //定义拦截器 |
说明:
preHandle()
方法:在目标资源方法运行前运行。返回true:放行;返回false:不放行postHandle()
方法:在目标资源方法运行后运行。afterCompletion()
方法:在视图渲染完毕后运行(最后运行)。
然后创建config.WebConfig
配置类,用于注册拦截器:
1 | //表示当前类为一个配置类 |
- 通过
registry.addInterceptor()
方法添加指定的拦截器。
addPathPatterns()
方法:需要拦截哪些资源excludePathPatterns()
方法:不需要拦截哪些资源
拦截路径 含义 举例 /*
一级路径 能匹配 /users
、/depts
、/login
,
不能匹配/users/1
/**
任意级路径 能匹配 /users
、/users/1
、/users/1/2
/users/*
/users
下的一级路径能匹配 /users/1
,
不能匹配/users/1/2
、/depts
/users/**
/users
下的任意级路径能匹配 /users
、/users/1
、/users/1/2
,
不能匹配/depts
最后创建一个controller.TestController
类,用于测试拦截器效果:
1 |
|
-
正确的登录请求:
返回的JWT令牌:
1
eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJodWF6aHUiLCJleHAiOjE3MjM0NDcxMzV9.YWwz1QXkeA0Av4vs4G2EKrBq4qlhIQ8YdpZvmZwFjiw
-
错误的登录请求:
-
正确的测试请求:
在请求头(Headers)中添加
token
字段,其值为需要携带的令牌。 -
错误的测试请求(未携带JWT令牌):
-
错误的测试请求(携带错误的JWT令牌):
后记
至此,Web最常见的一些业务操作记录完毕。