JWT介绍

什么是JWT?

        Json Web Token(JWT) 是一个开放标准(RFC 7519),它定义了一种紧凑的,自包含的方式,用于在各方之间以json对象安全地传输信息,此信息可以验证和信任.因为它是数字签名的,jwt可以使用加密算法(使用HMAC 算法) 或使用RSA或ECDSA 的公钥/私钥进行签名.

        通俗的讲:

        JWT就是通过json格式作为Web应用程序中的令牌,用于在各方之间安全地将信息以JSON的形式传输,在数据传输过程中.还可以对数据进行加密,签名等相关处理.

JWT的使用场景

 授权:
        这是使用JWT的最常见方案。 一旦用户登录,每个后续请求将包括 JWT,从而允许用户访问该令牌允许的路由,服务和资源。单点登录是当今广泛使用 JWT 的一项功能,因为它的开销很小并且可以在不同的域中轻松使用。

信息交换:
        JSON Web Token是在各方之间安全地传输信息的好方法。因为可以对JWT进行签名(例如,使用公钥/私钥对),所以您可以确保发件人是他们所说的人。此外,由于签名是使用标头和有效负载计算的,因此您还可以验证内容是否遭到篡改。

JWT认证过程

        

1.首先,前端通过 Web 表单将自己的用户名和密码发送到后端的接口。这一过程一般是一个 HTTP POST请求。建议的方式是通过SSL加密的传输(https协议),从而避免敏感信息被嗅探。

2.后端核对用户名和密码成功后,将用户的id等其他信息作为 JWT Payload(负载),将其与头部分别进行Base64编码拼接后签名,形成一个JWT(Token)。形成的JWT就是一个形同lll.zzz.xxx的字符串。

3.后端将JWT字符串作为登录成功的返回结果返回给前端。前端可以将返回的结果保存在 localStorage 或 sessionStorage 上,退出登录时前端删除保存的JWT即可。

4.前端在每次请求时将 JWT 放入 HTTP Header 中的 Authorization 位。(解决 XSS 和 XSRF 问题)

5.后端检查是否存在,如存在验证JWT的有效性。例如,检查签名是否正确;检查Token是否过期;检查Token的接收方是否是自己(可选)。

6.验证通过后后端使用JWT中包含的用户信息进行其他逻辑操作,返回相应结果。
 

 

JWT与Session的差异:

        相同点是,它们都是存储用户信息;然而,Session是在服务器端的,而JWT是在客户端的

Session方式存储用户信息的最大问题在于要占用大量服务器内存,增加服务器的开销。

        而JWT方式将用户状态分散到了客户端中,可以明显减轻服务端的内存压力。

Session的状态是存储在服务器端,客户端只有session id;而Token的状态是存储在客户端。

JWT的优势:

  • 简洁: 可以通过URL,POST参数或者Http 请求头发送,因为数据量小,传输速度也快

  • 自包含:负载中包含了用户所需要的数据,避免多次查询数据库

  • 因为Token是以JSON加密的形式保存在客户端,所以JWT是跨语言的,原则上任何语言的Web项目都支持

  • 不需要在服务端保存会话信息,特别适用于分布式微服务.

 

JWT的结构

JSON Web令牌以紧凑的形式由三部分组成,这些部分由点(.)分隔,分别是:

  • 头部(header)

  • 载荷 (payload)

  • 签名(signature)

JWT通常如下所示: xxxxxx.yyyyyy.zzzzz

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJVc2VySWQiOjEyMywiVXNlck5hbWUiOiJhZG1pbiJ9.Qjw1epD5P6p4Yy2yju3-fkq28PddznqRj3ESfALQy_U

头部(Header)

标头通常由两部分组成:

  1. 令牌的类型(即JWT)
  2. 所使用的签名算法,例如 HMAC SHA256 或 RSA。
    它会使用 Base64 编码组成 JWT 结构的第一部分
{
  "alg": "HS256",		//alg:algorithm(算法)
  "typ": "JWT"			//typ:type(类型)
}

注意:Base64是一种编码,也就是说,它是可以被翻译回原来的样子来的,它并不是一种加密过程。

然后用Base64Url编码(该加密是可以对称解密的)得到头部: 即:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

 

 载荷 (payload)

        令牌的第二部分是有效负载,其中包含声明。声明是有关实体(通常是用户)和其他数据的声明。同样的,它会使用 Base64 编码组成 JWT 结构的第二部分。
        简单来说,Payload 中包含了用户所需要的信息,如用户id、用户名、权限等。(由于Base64可以被解码,所以不要放用户的敏感信息,如密码!)

{"sub": "1234567890", "name": "John Doe", "admin": true }

然后将其base64url加密,得到jwt的一部分

eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9

 

签名(Signature)

        前面两部分都是使用 Base64 进行编码的,即前端可以解开知道里面的信息。Signature 需要使用编码后的 header 和 payload 以及提供的密钥,使用 header 中指定的签名算法(HS256)进行签名。签名的作用是保证 JWT 没有被篡改过。(header、payload 被篡改时,由于签名基于header和payload生成,所以将无法通过验证)

        签名时需要用到前面编码过的两个字符串,以头部中指定的加密算法(HMACSHA256) 加密,就如下

HMACSHA256(
    base64UrlEncode(header) + "." +
    base64UrlEncode(payload),
    secret
)

 加密后再进行 base64url 编码最后得到的字符串就是 token 的第三部分

TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

注意:secret是保存在服务器端的,jwt的签发也是在服务端的,secret就是用来进行jwt的签发和jwt的验证,所以它就是你服务端的私钥,在任何场景都不应该流露出去,一旦客户端得知这个secret,那就意味着客户端可以自我签发jwt了

 签名的作用: 保证 JWT 没有被篡改过,原理如下:

HMAC 算法是不可逆算法,类似 MD5 和 hash ,但多一个密钥,密钥(即上面的 secret)由服务端持有,客户端把 token 发给服务端后,服务端可以把其中的头部和载荷再加上事先共享的 secret 再进行一次 HMAC 加密,得到的结果和 token 的第三段进行对比,如果一样则表明数据没有被篡改。

 

JWT总结

  • 因为json的通用性,所以JWT是可以跨语言支持的,像C#,JavaScript,NodeJS,PHP等许多语言都可以使用

  • 因为有了payload部分,所以JWT可以在自身存储一些其它业务逻辑所必要的非敏感信息

  • 便于传输,jwt的构成非常简单,字节占用很小,所以它是非常便于传输的

  • 它不需要在服务端保存会话信息,所以它易于应用的扩展安全相关

  • 不应该在jwt的payload部分存储敏感信息,因为该部分是客户端可解密的部分

  • 保护好secret私钥。该私钥非常重要

  • 如果可以,请使用https协议

<think>首先,用户的问题是:“我想了解JWT的相关介绍,并查找Java中可用的JWT工具类”。系统级指令要求我:使用中文回答;所有行内数学表达式用$...$;独立公式用$$...$$;LaTeX语法正确;生成相关问题;引用的段落末尾添加引用标识,如[^1]。 用户提供了引用: - 引用[1]:关于JWT介绍和java-jwt的使用,提到JWT是一个标准,支持多种语言,包括Java,并列出了一些Java实现库如java-jwt、jose4j、nimbus-jose-jwt、jjwt。还提到JWT官网。 - 引用[2]:介绍JWT结构,包括Header、Payload、Verify Signature三部分。 - 引用[3]:JWT工具类在Java中的依赖引入,指定了jjwt库的依赖坐标。 用户上一次的问题和我的回答:在对话历史中,用户的问题是“我想了解JWT的相关介绍,并查找Java中可用的JWT工具类”,这是我需要回答的。系统提示说“参考站内引用”,但我没有之前的对话历史在这个上下文中;只有当前用户输入提供了引用。 系统指令说:“上述引用仅供参考,并不是用户真正的需求,请尽可能多的参考用户上一次的问题和你的回答。” 但在对话历史中,用户这是第一次问这个问题,所以没有“上一次的问题和回答”。用户输入的开头是“参考站内引用”,然后提供了三个引用。所以,我应该基于这些引用来回答。 关键点: - JWT介绍JWTJSON Web Token)是什么?它是一个开放标准(RFC 7519),用于在各方之间安全传输信息作为JSON对象。 - 从引用[1]:JWT是一个标准,支持多种语言,包括Java。列出Java实现库:java-jwt、jose4j、nimbus-jose-jwt、jjwt- 从引用[2]:JWT结构有三部分:Header、Payload、Verify Signature。 - 从引用[3]:在Java中使用jjwt库的依赖示例。 我需要结构化回答: - 首先,介绍JWT- 然后,解释JWT的结构。 - 接着,介绍Java中可用的JWT工具类,并提供依赖和代码示例。 - 最后,生成相关问题。 回答结构: 1. **JWT介绍**:简要解释什么是JWT、用途、优点。 2. **JWT结构**:详细说明Header、Payload、Verify Signature。 3. **Java中的JWT工具类**:列出常见的库,重点介绍jjwt (因为引用[3]提供了它),并给出代码示例。 4. **相关问题**:生成至少3个相关问题。 使用中文回答。 添加引用标识:在引用相关部分时,在末尾添加[^1]、[^2]、[^3]。 数学表达式:用户问题中没有涉及数学表达式,所以我可以不使用,但如果需要,确保格式正确。可能不需要,因为是JWT主题。 代码块:提供Java代码示例时,使用代码块格式。 生成相关问题:在回答末尾,添加“相关问题”部分。 </think>### JWT介绍及Java中的JWT工具类 JWTJSON Web Token)是一种开放标准(RFC 7519),用于在各方之间安全传输信息作为JSON对象。它常用于身份验证和信息交换,特别是在Web应用和API中,优势包括简洁性(基于JSON格式)、自包含性(Token本身包含所有必要信息)和易于跨语言实现[^1]。JWT的核心用途是确保数据的完整性和真实性,通过数字签名或加密机制保护数据不被篡改。 #### JWT的结构 JWT由三部分组成,各部分之间用点(.)分隔,形成如`Header.Payload.VerifySignature`的格式: - **Header(数据头)**:包含Token的元数据,如加密算法(例如HS256或RS256)和类型(通常为JWT)。例如:`{"alg": "HS256", "typ": "JWT"}`。 - **Payload(数据体)**:存储实际数据(称为claims),包括标准claims(如`iss`签发者、`exp`过期时间)或自定义claims。Payload中的数据可以是任意JSON对象,但需避免存储敏感信息。 - **Verify Signature(验证签名)**:用于验证Token的完整性和来源。签名基于Header和Payload,使用密钥生成。验证时,服务器重新计算签名并比对,确保Token未被篡改[^2]。 这种结构确保了JWT的轻量化(适合HTTP头传输)和安全性,但需注意:JWT本身不加密数据(除非使用JWE),因此敏感数据应额外处理。 #### Java中可用的JWT工具类 在Java生态系统中,有多种JWT库可用于生成、解析和验证JWT。以下是常用库的列表: - **java-jwt**:一个轻量级库,支持基本JWT操作。 - **jose4j**:功能全面的库,支持JWT、JWS和JWE标准。 - **nimbus-jose-jwt**:基于JOSE标准的库,适用于高级场景(如OAuth 2.0)。 - **jjwt**:流行且易用的库,由Apache 2.0许可证授权,适合快速开发和集成[^1][^3]。 其中,**jjwt**是最常用的工具类之一,下面以它为例,展示Java中的基本使用方法。 ##### 使用jjwt库的工具类示例 首先,在项目中添加依赖(Maven项目): ```xml <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> <!-- 版本可更新至最新 --> </dependency> ``` 以下是一个简单的Java工具类,实现JWT的生成和解析: ```java import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import io.jsonwebtoken.Claims; import java.util.Date; public class JwtUtils { // 密钥(实际应用中应从安全配置加载) private static final String SECRET_KEY = "mySecretKey"; // 生成JWT public static String generateToken(String subject, long expirationMillis) { return Jwts.builder() .setSubject(subject) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() + expirationMillis)) .signWith(SignatureAlgorithm.HS256, SECRET_KEY) .compact(); } // 解析并验证JWT public static Claims parseToken(String token) { return Jwts.parser() .setSigningKey(SECRET_KEY) .parseClaimsJws(token) .getBody(); } // 示例用法 public static void main(String[] args) { String token = generateToken("user123", 3600000); // 1小时有效 System.out.println("Generated JWT: " + token); Claims claims = parseToken(token); System.out.println("Subject: " + claims.getSubject() + ", Expiration: " + claims.getExpiration()); } } ``` - **说明**:此工具类实现JWT的生成(使用HS256算法)和解析。实际应用中,密钥应存储在安全配置中,并使用更安全的算法(如RS256)处理敏感数据[^2][^3]。 #### 注意事项 - 安全建议:避免在Payload中存储敏感数据(如密码),并使用HTTPS传输JWT- 性能优化:对于高并发场景,考虑缓存令牌验证结果。 - 库选择:jjwt库适合小型项目,而nimbus-jose-jwt更适合企业级应用(如支持OIDC)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值