JWT验证原理

一、什么是JWT?

JSON Web Token(JWT),是一个开放安全的行业标准,用于多个系统之间传递安全可靠的信息.

JWT是什么样子的结构?

JSON Web Token说到底也是一个token字符串,它由三部分组成,头部、载荷与签名。 
如下图 红色的为Header,指定token类型与签名类型,紫色的为载荷(playload),存储用户id等关键信息,最后蓝色的为签名,保证整个信息的完整性,可靠性.

这里写图片描述

头部(Header) 
JWT的头部用于描述关于该JWT的最基本的信息,例如其类型以及签名所用的算法等。这可以被表示成一个JSON对象。

{
  "typ": "JWT",
  "alg": "HS256"
}
  •  

在这里,我们说明了这是一个JWT,并且我们所用的签名算法是HS256算法。

对它进行Base64编码,之后的字符串就成了JWT的Header(头部)。

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

载荷(playload) 
在载荷(playload)中定义了以下属性

iss: 该JWT的签发者 
sub: 该JWT所面向的用户 
aud: 接收该JWT的一方 
exp(expires): 什么时候过期,这里是一个Unix时间戳 
iat(issued at): 在什么时候签发的

也可以用一个JSON对象来描述 
将上面的JSON对象进行[base64编码]可以得到下面的字符串。这个字符串我们将它称作JWT的Payload(载荷)。

eyJpc3MiOiIyOWZmMDE5OGJlOGM0YzNlYTZlZTA4YjE1MGRhNTU0NC1XRUIiLCJleHAiOjE1MjI0OTE5MTV9

签名(Signature) 
在官方文档中是如下描述的

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)
  • 即如下操作 

将上面的两个[base64编码]后的字符串都用句号.连接在一起(头部在前),就形成了如下字符串

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiIyOWZmMDE5OGJlOGM0YzNlYTZlZTA4YjE1MGRhNTU0NC1XRUIiLCJleHAiOjE1MjI0OTE5MTV9

最后,我们将上面拼接完的字符串用HS256算法进行加密。在加密的时候,我们还需要提供一个密钥(secret)。那么就可以得到我们加密后的内容 
P-k-vIzxElzyzFbzR4tUxAAET8xT9EP49b7hpcPazd0 
这个就是我们JWT的签名了

签名的目的 
最后一步签名的过程,实际上是对头部以及载荷内容进行签名。一般而言,加密算法对于不同的输入产生的输出总是不一样的。

所以,如果有人对头部以及载荷的内容解码之后进行修改,再进行编码的话,那么新的头部和载荷的签名和之前的签名就将是不一样的。而且,如果不知道服务器加密的时候用的密钥的话,得出来的签名也一定会是不一样的。

服务器应用在接受到JWT后,会首先对头部和载荷的内容用同一算法再次签名。那么服务器应用是怎么知道我们用的是哪一种算法呢?别忘了,我们在JWT的头部中已经用alg字段指明了我们的加密算法了。

如果服务器应用对头部和载荷再次以同样方法签名之后发现,自己计算出来的签名和接受到的签名不一样,那么就说明这个Token的内容被别人动过的,我们应该拒绝这个Token,返回一个HTTP 401 Unauthorized响应。

JWT是一个怎样的流程? 
先上个官方文档的图 
这里写图片描述
流程如下:

  1. 客户端使用账户密码请求登录接口
  2. 登录成功后服务器使用签名密钥生成JWT ,然后返回JWT给客户端
  3. 客户端再次向服务端请求其他接口时带上JWT
  4. 服务端接收到JWT后验证签名的有效性.对客户端做出相应的响应

为什么要使用JWT?

与Session的区别

session实际上是基于cookie来传输的,最重要的session信息是存储在服务器的,所以服务器每次可以通过cookie中的sessionId获取到当前会话的用户,对于单台服务器这样做没问题,但是对于多台就涉及到共享session的问题了,而且认证用户的增多,session会占用大量的服务器内存.

jwt是存储在客户端的,服务器不需要存储jwt,jwt里面有用户id,服务器拿到jwt验证后可以获得用户信息.也就实现了session的功能,但是相比session,jwt是无状态的,其不与任何机器绑定,只要签名秘钥足够的安全就能保证jwt的可靠性.

JWT方案中token的安全问题 
token被劫持

按照JWT的流程,jwt是存储在客户端的,服务器不需要存储jwt;客户端每次发送请求时携带token,然后到服务端验证token是否正确,是否过期,然后解码出携带的用户信息。根据以上流程 
如果token在传输过程被攻击者截取了,那么对方就可以伪造请求,利用窃取的Token模拟正常请求,实现用户的正常操作,而服务器端对此完全不知道,因为JWT机制是无状态的。 
我们要明白JWT解决的是认证与授权的问题,上述劫持或者类似的中间人攻击是JWT不可避免的,也是其他认证与授权方式不可避免的,想避免可以使用HTTPS

 

### JWT 验证实现方案 JWT(JSON Web Token)是一种广泛使用的安全令牌标准,用于身份验证和信息传递。其验证过程的核心在于确保接收到的 JWT 是合法且未被篡改的。 #### 1. **JWT 验证原理** JWT 的结构分为三部分:Header、Payload 和 Signature。验证的主要步骤如下: - 对 Header 进行 Base64 URL 解码,获取签名所用的算法。 - 使用相同的逻辑重新计算 header 和 payload 的签名。 - 将新生成的签名与 JWT 中的第三部分进行对比。如果两者一致,则说明该 JWT 合法;否则视为非法或已被篡改[^1]。 接收方在生成签名时需使用与发送方一致的密钥,这是保证数据完整性和真实性的重要条件。 #### 2. **Node.js 环境下的 JWT 验证实现** 以下是基于 Node.js 的 JWT 验证代码示例: ```javascript const jwt = require('jsonwebtoken'); // 验证函数 function verifyToken(token, secretKey) { try { const decoded = jwt.verify(token, secretKey); console.log("Decoded Payload:", decoded); // 输出解码后的负载信息 return true; } catch (err) { console.error("Verification failed", err.message); return false; } } // 测试用例 const token = 'your-jwt-token'; // 替换为实际的 JWT const secretKey = 'your-secret-key'; // 替换为实际的密钥 verifyToken(token, secretKey); ``` 此代码通过 `jsonwebtoken` 库实现了 JWT 的解析与验证功能[^2]。 #### 3. **Java 环境下 JWT 验证及其常见错误解决** 对于 Java 开发者来说,可能需要引入额外的依赖来处理某些环境中的兼容性问题。例如,在 JDK 版本较高时可能会因缺少必要的库而无法生成或验证 JWT。此时可以通过添加以下 Maven 依赖解决问题[^3]: ```xml <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency> <dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>2.1</version> </dependency> ``` 这些依赖能够有效修复由于高版本 JDK 缺失 jaxb-api 导致的异常。 #### 4. **JWT 登录踢出机制的设计思路** 当应用程序需要限制同一账户仅能在单一设备上登录时,可采用以下策略之一: - 设置较短的有效期(如五分钟),并配合刷新令牌(Refresh Token)。这种方式无需存储大量会话状态即可达到目的。 - 结合 Session 和 JWT 使用,利用 Session 记录当前活跃用户的唯一标识符,并定期同步至分布式缓存服务中以便快速查找已登出用户的信息。 - 更加严格的控制方式是对 IP 地址或其他网络特征加以绑定,从而进一步增强安全性[^5]。 ### 总结 以上介绍了关于如何实现以及排查 JWT 验证过程中可能出现的一些典型问题的具体方法论。无论是选用哪种技术栈开发的应用程序都可以找到适合自己的解决方案。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值