前置背景
- 为什么写下这篇文章?
因为需要实现一个设备管理系统的权限管理模块,在查阅很多博客以及其他网上资料之后,发现重复、无用的博客很多,因此写一篇文章来记录,以便后面复习。
-
涉及的知识点主要有下列知识点:
- JWT
- shiro
-
书写顺序
- 首先使用springboot 结合 jwt完成前后端分离的token认证。
- 其次结合shiro完成shiro+jwt的前后端分离的权限认证管理。
权限管理的表结构设计
- 一个user可以拥有多个role,一个role也可以被多个user拥有, 一个 角色拥有多个权限即功能,一个权限可以被多个role拥有。
用户、角色、权限类
表结构图
Part1: spring boot + jwt
这一部分就可以完成前后端分离项目的登录功能。在不需要添加权限管理的情况下,就可以满足需求。
Spring boot集成JWT
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.8.2</version>
</dependency>
复制代码
思路整理
- 为什么需要使用到jwt?
- jwt是什么
- Java如何使用jwt
在前后端分离的项目中,由服务器使用的会话管理session
无法满足需求。需要一种技术做会话管理。因此选择JWT
。 Json web token (JWT)
: 是目前流行的跨域认证解决方案,是一种基于 Token 的认证授权机制。 JWT
的数据结构分为三部分 header payload signature。 这三部分通过.
连接,如下
Token示例:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.
eyJwYXNzd29yZCI6InN1cGVyIiwiZXhwIjoxNjYzMTIzNDgzLCJ1c2VybmFtZSI6InN1cGVyIn0.
5xVg6IuOLe_uVwwOaeyRDbTHRjfmIbNsnb-DP9-Ic20
复制代码
如何使用:当用户登录系统后,服务端给前端发送一个基于用户信息创建的token,然后在此后的每一次前端请求都会携带token。服务端通过拦截器拦截请求,同时验证携带的token是否正确。如果正确则放行请求,不正确则拒绝通过。 思路流程图:
token的创建和验证
JWTUtil.java
负责创建和验证jwt格式的token
public class JWTUtil {
private static final long EXPIRE_TIME = 3 * 60 * 1000;//默认3分钟
//私钥
private static final String TOKEN_SECRET = "privateKey";
public static String createToken(UserEntity userModel) {
try {
// 设置过期时间
Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
log.info(String.valueOf(date));
// 私钥和加密算法
Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
// 设置头部信息
Map<String, Object> header = new HashMap<>(2);
header.put("Type", "Jwt");
header.put("alg", "HSA256");
// 返回token字符串
return JWT.create()
.withHeader(header)
.withClaim("username", userModel.getUsername())
.withExpiresAt(date)
.sign(algorithm);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 检验token是否正确
*
* @param **token**
* @return
*/
public static boolean verifyToken(String token, String username) {
log.info("验证token..");
try {
Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
JWTVerifier verifier = JWT.require(algorithm)
.withClaim("username",username).build();
// 验证不通过会抛出异常。
verifier.v