SpringBoot整合JWT认证机制实现接口鉴权
什么是JWT认证机制
Json Web Token(缩写JWT)是目前最流行的跨域认证解决方案
session登录的认证方案是看,用户从客户端传递用户名和密码登录信息,服务端认证后将信息储存在session中,将session_id放入cookie中,以后访问其他页面,服务器都会带着cookie,服务端会自动从cookie中获取session_id,在从session中获取认证信息。
JWT的解决方案是,将认证信息返回个客户端,储存在客户端,下次访问其他页面,需要从客户端传递认证信息回服务器端。
JWT结构
一个完整的Json Web Token将分为三个部分,header(头部)、payload (负载) 、signature (签名)。
头部 (header)
头部通常由两部分组成:令牌的类型(即JWT)和所使用的签名算法,例如HMAC SHA256或RSA。
例如:
{
"alg": "HS256",
"typ": "JWT"
}
然后,此JSON被 Base64Url 编码以形成JWT的第一部分。
有效载荷(payload)
令牌的第二部分是有效负载(payload),其中包含声明(claims)。声明是有关实体(通常是用户)和其他数据的声明。比如:registered, public, and private claims.
一个Payload的例子可以是
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
然后,对有效负载进行Base64Url编码,以形成JSON Web令牌的第二部分。
签名 (signature)
要创建签名部分,您必须获取编码的标头,编码的有效载荷,机密,标头中指定的算法,并对其进行签名。
例如,如果要使用HMAC SHA256算法,则将通过以下方式创建签名:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
签名用于验证消息在整个验证过程中没有更改,并且如果使用私钥进行令牌的签名的,它还可以验证JWT的发件人是谁。
最后,一个完整的Token可以是下面这样
SpringBoot与JWT的整合
通过在SpringBoot中整合JWT,可以构建有认证机制的Restful Web服务,或者实现前后端分离开发中的状态认证(比如和Vue进行整合)。
导入相关Maven依赖
<!-- JWT Dependency-->
<!-- https://mvnrepository.com/artifact/com.auth0/java-jwt -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.10.3</version>
</dependency>
编写JWT的工具类
这里设置了每个Token的失效时间为1个小时以后,payload中存储了用户的uid和用户名等信息,tokenPassword为进行HMAC256签名的私钥,需要进行安全性的存储。
public class JwtUtil {
private static final String tokenPassword = "your_secret_key";
public static String getToken(User user) {
Instant dateTime = LocalDateTime.now().plusHours(1).toInstant(OffsetDateTime.now().getOffset());
Date expireTime = Date.from(dateTime);
String token;
token = JWT.create()
.withClaim("uid", user.getId())
.withClaim("username", user.getUsername())
.withIssuedAt(new Date())
.withExpiresAt(expireTime)
.sign(Algorithm.HMAC256(tokenPassword));
return token;
}
public static int verifyToken(String token) {
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(tokenPassword)).build();
try {
jwtVerifier.verify(token);
} catch (TokenExpiredException e) {
return Status.WARNING;
} catch (JWTVerificationException e) {
return Status.FORBIDDEN;
}
return Status.SUCCESS;
}
}
构建继承HandlerInterceptor的SpringBoot拦截器
@Component
public class UserInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
String token = request.getHeader("Authorization").substring(7);
int result = JwtUtil.verifyToken(token);
if (result == Status.FORBIDDEN) {
response.setStatus(401);
return false;
} else if (result == Status.WARNING) {
request.setAttribute("tokenExpired", true);
}
request.setAttribute("tokenExpired", false);
return true;
}
}
构建WebConfigurer类来注入拦截器
@Configuration
public class WebConfigurer implements WebMvcConfigurer {
UserInterceptor userInterceptor;
public WebConfigurer(UserInterceptor userInterceptor) {
this.userInterceptor = userInterceptor;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(userInterceptor).addPathPatterns("/api/user/**");
}
// 解决浏览器端跨站安全机制的问题
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("*")
.allowedHeaders("Authorization");
}
}
经过上述的操作,在对匹配的路径进行请求后,拦截器将会验证HTTP Headers中的Authorization头中的Token,并进行对应的传递或响应。
提示
我的博客即将同步至腾讯云+社区,邀请大家一同入驻:
https://cloud.tencent.com/developer/support-plan?invite_code=1v5xqqcp1en4i
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- LeetCode51|寻找旋转排序数组中的最小值
- Yapi 可视化接口平台安装实践
- LeetCode50|搜索旋转排序数组II
- LeetCode49|搜索旋转排序数组
- 第13天:NLP补充——RNN算法
- Android自定义跑马灯效果(适合任意布局)
- Handler Looper.prepareMainLooper();源码分析
- Caused by: java.lang.IllegalStateException: System services not available to Activities before onCre
- Actuator与服务监控
- Typecho 文章置顶插件:Sticky
- SpringBoot源码学习(一)
- Typecho Markdown编辑器粘贴剪贴板图片插件:PasteImage
- SpringBoot源码学习(二)
- 【React+Typescript+Antd】Echarts滑动卡顿问题解决
- 13个超实用的JavaScript数组操作技巧