JWT令牌技术

1. 什么是JWT令牌

JSON Web Token(JWT)是一种使用JSON格式传递数据的网络令牌技术,它是一个开放的行业标准(RFC 7519),它定义了一种简洁的、自包含的协议格式,用于在通信双方传递json对象,传递的信息经过数字签名可以被验证和信任,它可以使用HMAC算法或使用RSA的公钥/私钥对来签名,防止内容篡改。官网:JWT

使用JWT可以实现无状态认证:

传统的基于session的方式是有状态认证,用户登录成功将用户的身份信息存储在服务端,这样加大了服务端的存储压力,并且这种方式不适合在分布式系统中应用。

如果是基于令牌技术在分布式系统中实现认证则服务端不用存储session,可以将用户身份信息存储在令牌中,用户认证通过后认证服务颁发令牌给用户,用户将令牌存储在客户端,去访问应用服务时携带令牌去访问,服务端从jwt解析出用户信息。这个过程就是无状态认证。

2. JWT令牌的优缺点

2.1 JWT令牌的优点

  • 紧凑性:JWT 是 URL 安全的,可以在 URL 中传输。
  • 自包含:JWT 包含了验证用户身份所需的信息,因此可以减少服务器的数据库查询次数。
  • 跨域支持:由于 JWT 是无状态的,适合在跨域场景中使用。
  • 无状态:JWT 是无状态的,不需要在服务器端保存会话信息,这使得它非常适合微服务架构。

2.2 JWT令牌的缺点

  • 无状态导致的难以撤销:一旦 JWT 发放出去,除非它过期或在服务器上设置一个黑名单,否则无法撤销它。
  • 较大的 Payload 可能导致开销:如果 JWT 包含太多信息,可能会影响传输效率。

3. JWT令牌的组成

JWT令牌由三部分组成,Header(头部)、Payload(负载)、Signature(签名);

它们由点 (.) 分隔,结构如下:

Header.Payload.Signature

3.1 Header(头部)

Header 通常包含两部分信息:

  • 类型:表示这是一个 JWT(通常写为 "JWT")。
  • 签名算法:例如 HMAC SHA256 或 RSA。

一个典型的 Header 如下:

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

这个 JSON 被 Base64 编码后形成 JWT 的第一部分。

3.2 Payload(负载)

第二部分是负载,内容也是一个json对象,它是存放有效信息的地方,它可以存放jwt提供的信息字段,比如:iss(签发者),exp(过期时间戳), sub(面向的用户)等,也可自定义字段。

此部分不建议存放敏感信息,因为此部分可以解码还原原始内容。

例如,一个典型的 Payload 可能如下:

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

这个 JSON 被 Base64 编码后形成 JWT 的第二部分。

3.3 Signature(签名)

签名部分是用来验证消息没有被篡改过。

首先将 Header 和 Payload 进行 Base64 编码后组合,编码后使用点(.)连接组成字符串,然后使用 Header 中指定的算法和一个密钥进行签名。

假设使用的是 HMAC SHA256 算法,签名部分的生成方式如下:

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

base64UrlEncode(header):jwt令牌的第一部分。

base64UrlEncode(payload):jwt令牌的第二部分。

secret:签名所使用的密钥。

为什么JWT可以防止篡改:

第三部分使用签名算法对第一部分和第二部分的内容进行签名,常用的签名算法是 HS256,常见的还有md5,sha 等,签名算法需要使用密钥进行签名,密钥不对外公开,并且签名是不可逆的,如果第三方更改了内容那么服务器验证签名就会失败,要想保证验证签名正确必须保证内容、密钥与签名前一致。

4. JWT 的使用流程

4.1 用户登录

用户输入凭据(如用户名和密码),服务器验证成功后,会生成一个 JWT,包含用户的一些信息(如用户 ID、角色等),并返回给客户端。

4.2 客户端存储 JWT

客户端通常将 JWT 存储在浏览器的 localStoragesessionStorage 中,或者作为一个 Cookie。

4.3 客户端每次请求时发送 JWT

客户端在每次请求时将 JWT 附带在 HTTP 请求头的 Authorization 字段中,格式如下:

Authorization: Bearer <token>

4.4 服务器验证 JWT

服务器接收到请求后,验证 JWT 的有效性(如签名是否正确,是否过期等)。如果 JWT 有效,服务器就处理请求,否则返回错误状态(如 401 未授权)。

5. 安全性注意事项

  • 使用 HTTPS:确保通过 HTTPS 传输 JWT,以防止中间人攻击。
  • 使用强大的签名算法:避免使用不安全的签名算法,例如 none 或弱加密算法。
  • 定期刷新 JWT:使用短期 JWT,并提供刷新机制,以减少被盗用的风险。
  • 保护好密钥:签名 JWT 的密钥必须妥善保管,不应泄露。

6. 使用示例

6.1 创建 JWT

 在 Java 中,你可以使用 java-jwt 库来创建和验证 JWT。创建一个简单的 JWT 示例:

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;

public class JWTExample {
    public static void main(String[] args) {
        String token = JWT.create()
                .withClaim("userId", 123)
                .withClaim("role", "admin")
                .sign(Algorithm.HMAC256("secret"));
        System.out.println(token);
    }
}

6.2 验证 JWT

同样地,你可以使用 java-jwt 库来验证 JWT:

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.JWTVerifier;

public class JWTVerifyExample {
    public static void main(String[] args) {
        try {
            Algorithm algorithm = Algorithm.HMAC256("secret");
            JWTVerifier verifier = JWT.require(algorithm).build();
            DecodedJWT jwt = verifier.verify(token);
            System.out.println("User ID: " + jwt.getClaim("userId").asInt());
        } catch (JWTVerificationException exception){
            // 无效的签名/声明
            exception.printStackTrace();
        }
    }
}
  • 7
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cyt涛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值