news 2026/6/15 19:40:02

JWT令牌技术

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JWT令牌技术

目录

  • 一、令牌技术概览
  • 二、JWT的核心组成与结构
    • 1、Header(头)
    • 2、Payload(载荷)
    • 3、Signature(签名)
    • 4、Base64编码
    • 5、JWT的认证流程
  • 三、使用JWT令牌
    • 1、引入JWT令牌的依赖
    • 2、引入JWT令牌的工具类
    • 3、生成JWT令牌
    • 4、统一拦截器配置
  • 四、总结

一、令牌技术概览

在登录认证中,令牌是用户的身份标识,是合法的身份凭证,好像十分神秘和高大上,但其本质是一个字符串

如果使用令牌技术进行会话跟踪,在浏览器发起请求,请求登录接口如果登录成功,那么就在服务端生成一个令牌令牌就是用户的合法身份凭证,在响应数据的时候,就可以将令牌直接响应给前端
前端程序接收到令牌之后,就需要将令牌存储起来,可以存储在Cookie中,也可以存储在localStorage这样的其他存储空间。之后,在后续的每一次请求中,都需要携带令牌服务端的统一拦截器需要校验令牌的有效性。如果令牌有效,则说明用户已经执行了登录操作,拦截器就可以放行;如果令牌无效(解析令牌报错),那么则说明用户没有执行登录操作,拦截器就需要拦截,并返回错误代码,让用户登录。整个流程如下图所示:

此时,在同一个会话的多次请求之间,我们就通过将数据存储在令牌中的方式完成了数据共享。令牌技术有很多优点,比如:支持多端,不但支持PC端,而且支持移动端;令牌技术也可以解决服务器集群的认证问题,因为只需要成功解析令牌,就可以证明令牌是有效的,是无需在服务器存储的(存储在Redis;令牌的安全性也非常强悍。但也是因为其强悍的性能,令牌使用起来会更加的复杂,但是这些劣势在优势面前就不值一提了。

二、JWT的核心组成与结构

令牌的形式有很多,本文讲解功能强大使用最广泛的JWT令牌。JWT令牌(JSON Web Token),定义了一种简洁的、自包含的格式,可用于通信双方以Json数据格式安全的传输信息。
简洁JWT令牌的本质就是字符串,可以作为请求参数或者在请求头中直接传递。(可以存储在CookieHeader里面,建议存储在Header里面)。
自包含JWT可以自己定义需要存储的信息
安全JWT令牌虽然是一个字符串,但是可以根据需求,在令牌中存储自定义的数据内容,比如在登录操作中,可以在JWT令牌中存储用户相关信息
JWT由三部分Base64编码的字符串组成,以点号(.)分隔:Header.Payload.Signature

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxIiwiaWF0IjoxNjg5NjYxODUwLCJleHAiOjE2OTA5NTc4NTB9.Bq0pExJcSgaQD94qAYVSx4W__K8FWGeY7iUJKMyTIYFofZoqa2VfEvl8Na96kt2wYbjFImHmQntkdce6cHQ8_A

1、Header(头)

该部分主要是记录令牌类型、令牌使用的签名算法等。例如:

{"typ":"JWT","alg":"HS512"}

从这个Header信息就可以看出:这是一个JWT令牌,使用了HS512签名算法。

‌alg‌:指定加密算法(如HS256、RS256),确保令牌完整性。
‌typ‌固定为"JWT",标识令牌类型。

2、Payload(载荷)

该部分主要是携带一些自定义的信息,或者一些默认的信息等,例如:

{"sub":"1","iat":1689661850,"exp":1690957850}

从这个Payload信息可以看出:这个令牌携带的数据是一个用户数据,sub为1,iat为1689661850。

载荷存储用户声明(Claims),分为三类:
‌注册声明(Registered Claims)‌:预定义字段(如sub表示主题,exp表示过期时间)。
‌公共声明(Public Claims)‌:自定义字段(如role: “admin”)。
‌私有声明(Private Claims)‌:业务特定数据(如用户ID)。

3、Signature(签名)

这个部分主要是令牌的签名签名可以防止Token被篡改,可以提高令牌的安全性。其构成是将HeaderPayload两个部分,加入指定密钥(Secret),并通过指定的签名算法计算而来。正是因为数字签名,所以说JWT令牌是非常安全的,一旦令牌中的任何一个部分、任何一个字符被篡改了,整个令牌在校验时都会失效。

4、Base64编码

JWT令牌是如何将原始的Json数据,转变为字符串的呢?在生成JWT令牌的时候,对原始数据进行了Base64编码这并非是一种加密方式,只是一种编码方式)。
Base64编码:是一种基于64个可打印的字符来表示二进制数据的编码方式。所使用的64个字符分别是A到Z、a到z、0-9,一个加号(+),一个斜杠(/),加起来就是64个字符。任何数据经过base64编码之后,最终就会通过这64个字符来表示。在有些情况下,Basae64编码可能会出现一个等号(=)。等号是一个补位的符号。

5、JWT的认证流程


1.用户登录‌:客户端提交凭证(如用户名/密码)至认证服务器。
‌2.令牌签发‌:服务器验证凭证后,生成JWT并返回客户端。
3‌.令牌存储‌:客户端将JWT保存于localStorageCookie中(更建议存在headers里面)。
4‌.请求携带‌:客户端在后续请求头中添加Token。
‌5.服务端验证‌:服务器解密签名、检查过期时间(exp)和发行者(iss),验证通过后执行业务逻辑。

三、使用JWT令牌

1、引入JWT令牌的依赖

想要使用JWT令牌,首先需要引入JWT对应的Maven坐标:

<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency>

2、引入JWT令牌的工具类

在引入了JWT依赖之后,就可以使用对应的工具类JwtUtil提供的API来完成JWT令牌的生成与校验:

packagecom.sky.utils;importio.jsonwebtoken.Claims;importio.jsonwebtoken.JwtBuilder;importio.jsonwebtoken.Jwts;importio.jsonwebtoken.SignatureAlgorithm;importjava.nio.charset.StandardCharsets;importjava.util.Date;importjava.util.Map;publicclassJwtUtil{/** * 生成jwt * 使用Hs256算法, 私匙使用固定秘钥 * * @param secretKey jwt秘钥 * @param ttlMillis jwt过期时间(毫秒) * @param claims 设置的信息 * @return */publicstaticStringcreateJWT(StringsecretKey,longttlMillis,Map<String,Object>claims){// 指定签名的时候使用的签名算法,也就是header那部分SignatureAlgorithmsignatureAlgorithm=SignatureAlgorithm.HS256;// 生成JWT的时间longexpMillis=System.currentTimeMillis()+ttlMillis;Dateexp=newDate(expMillis);// 设置jwt的bodyJwtBuilderbuilder=Jwts.builder()// 如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的.setClaims(claims)// 设置签名使用的签名算法和签名使用的秘钥.signWith(signatureAlgorithm,secretKey.getBytes(StandardCharsets.UTF_8))// 设置过期时间.setExpiration(exp);returnbuilder.compact();}/** * Token解密 * * @param secretKey jwt秘钥 此秘钥一定要保留好在服务端, 不能暴露出去, 否则sign就可以被伪造, 如果对接多个客户端建议改造成多个 * @param token 加密后的token * @return */publicstaticClaimsparseJWT(StringsecretKey,Stringtoken){// 得到DefaultJwtParserClaimsclaims=Jwts.parser()// 设置签名的秘钥.setSigningKey(secretKey.getBytes(StandardCharsets.UTF_8))// 设置需要解析的jwt.parseClaimsJws(token).getBody();returnclaims;}}

3、生成JWT令牌

Map<String,Object>claims=newHashMap<>();claims.put(JwtClaimsConstant.EMP_ID,employee.getId());Stringtoken=JwtUtil.createJWT(jwtProperties.getAdminSecretKey(),jwtProperties.getAdminTtl(),claims);

4、统一拦截器配置

packagecom.sky.interceptor;importcom.sky.constant.JwtClaimsConstant;importcom.sky.context.BaseContext;importcom.sky.properties.JwtProperties;importcom.sky.utils.JwtUtil;importio.jsonwebtoken.Claims;importlombok.extern.slf4j.Slf4j;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Component;importorg.springframework.web.method.HandlerMethod;importorg.springframework.web.servlet.HandlerInterceptor;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;/** * jwt令牌校验的拦截器 */@Component@Slf4jpublicclassJwtTokenAdminInterceptorimplementsHandlerInterceptor{@AutowiredprivateJwtPropertiesjwtProperties;/** * 校验jwt * * @param request * @param response * @param handler * @return * @throws Exception */publicbooleanpreHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler)throwsException{//判断当前拦截到的是Controller的方法还是其他资源if(!(handlerinstanceofHandlerMethod)){//当前拦截到的不是动态方法,直接放行returntrue;}//1、从请求头中获取令牌Stringtoken=request.getHeader(jwtProperties.getAdminTokenName());//2、校验令牌try{log.info("jwt校验:{}",token);Claimsclaims=JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(),token);LongempId=Long.valueOf(claims.get(JwtClaimsConstant.EMP_ID).toString());log.info("当前员工id:",empId);BaseContext.setCurrentId(empId);//3、通过,放行returntrue;}catch(Exceptionex){//4、不通过,响应401状态码response.setStatus(401);returnfalse;}}}

四、总结

JWT令牌是现在越来越流行,使用越来越广泛的会话跟踪技术,可以在多端使用,并且有极强的安全性能,还可以应对服务器集群问题,是解决登录认证问题的最佳选择。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/15 15:17:08

PSQL高效命令大全:比传统方法快10倍的技巧

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个PSQL效率工具包&#xff0c;包含以下功能&#xff1a;1) 常用命令快捷键 2) 复杂查询模板 3) 批量操作脚本 4) 性能分析工具 5) 自动补全功能 6) 历史命令搜索 7) 结果格式…

作者头像 李华
网站建设 2026/6/15 12:53:51

正则化在数据清洗中的5个实战技巧

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个数据清洗工具&#xff0c;内置常见正则表达式模板&#xff08;去空格、标准化日期、提取关键信息等&#xff09;。用户上传CSV文件后&#xff0c;可选择预处理模板或自定义…

作者头像 李华
网站建设 2026/6/15 2:59:20

电商系统中的MyBatis模糊搜索实战案例

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个电商商品搜索系统&#xff0c;功能要求&#xff1a;1. 商品多条件模糊搜索&#xff08;名称、分类、描述&#xff09;&#xff1b;2. 搜索建议功能&#xff08;输入时实时提…

作者头像 李华
网站建设 2026/6/15 14:58:19

1小时打造个性化Xshell配置管理工具

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个Xshell配置管理工具原型&#xff0c;具备&#xff1a;1. 会话配置导入导出&#xff1b;2. 主题样式批量更换&#xff1b;3. 快捷键自定义模板&#xff1b;4. 配置差异对比功…

作者头像 李华
网站建设 2026/6/15 13:47:56

Windows Server 2025 vs 2019:性能与效率全面对比

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个性能对比工具&#xff0c;能够测试Windows Server 2025和2019在相同硬件环境下的CPU、内存、磁盘I/O和网络性能。生成详细的对比报告&#xff0c;突出2025版本的改进点。点…

作者头像 李华
网站建设 2026/6/15 13:47:30

企业IT必看:批量卸载Office的自动化实践

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个企业级Office批量卸载工具&#xff0c;功能包括&#xff1a;1.AD域控集成扫描 2.多版本Office识别&#xff08;2013/2016/2019/O365&#xff09;3.静默卸载模式 4.日志记录…

作者头像 李华