news 2026/6/10 9:22:26

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/8 18:42:54

对比传统select,xm-select如何提升表单开发效率300%

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 生成一个对比测试页面&#xff0c;左侧使用原生HTML select实现多选功能&#xff0c;右侧使用xm-select实现相同功能。要求&#xff1a;1.都支持1000条数据加载&#xff0c;2.比较渲…

作者头像 李华
网站建设 2026/6/9 20:58:47

1小时原型开发:用DDS快速验证车联网通信方案

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 快速构建车联网DDS原型系统&#xff0c;要求&#xff1a;1)模拟5辆智能汽车的实时通信 2)实现紧急消息优先传输机制 3)可视化车辆位置和消息流。使用AI自动生成C基础框架&#xff0…

作者头像 李华
网站建设 2026/6/7 22:54:13

AI如何帮你快速找到正确的Maven仓库地址

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个工具&#xff0c;能够根据用户输入的依赖名称或描述&#xff0c;自动搜索并返回最相关的Maven仓库地址。工具应支持模糊匹配&#xff0c;能够解析pom.xml文件中的依赖项&am…

作者头像 李华
网站建设 2026/6/5 14:26:52

@requestmapping零基础入门指南

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个requestmapping学习应用&#xff0c;提供交互式教程和新手友好的界面。点击项目生成按钮&#xff0c;等待项目生成完整后预览效果 作为一名刚开始接触Spring框架的开发者&a…

作者头像 李华
网站建设 2026/6/9 13:07:57

电商大促期间Percona XtraBackup实战经验分享

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个电商数据库备份恢复演练系统&#xff0c;功能包括&#xff1a;1. 模拟高并发订单场景下的数据库负载 2. 使用Percona XtraBackup进行在线热备份 3. 自动化备份验证流程 4. …

作者头像 李华
网站建设 2026/6/10 6:38:32

1小时验证创意:用Yande入口原型获取用户反馈

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个Yande搜索引擎入口的最小可行产品(MVP)&#xff0c;包含核心搜索功能和结果展示。实现&#xff1a;1) 关键词输入和自动补全 2) 基本图片搜索结果展示 3) 简单的用户反馈收…

作者头像 李华