JWT:你真的了解它吗?

       大家好,我是石头~

       在数字化时代,网络安全和用户隐私保护成为了我们无法忽视的关键议题,也是我们作为一个后端开发的必修课。

       而在这个领域中,JWT(JSON Web Token)作为一种现代、安全且高效的会话管理机制,在各类Web服务及API接口中得到了广泛应用。

       那么,什么是JWT?

下载 (3).jfif

1、初识JWT

       JWT,全称为JSON Web Token,是一种开放标准(RFC 7519),用于在网络应用环境间安全地传输信息。

       它本质上是一个经过数字签名的JSON对象,能够携带并传递状态信息(如用户身份验证、授权等)。

       了解了JWT之后,那么它的组成结构又是怎样的?

2、JWT的结构

u=2288314449,1048843062&fm=253&fmt=auto&app=138&f=JPEG.webp

       如上图,JWT由三部分组成,通过点号(.)连接,这三部分分别是头部(Header)、载荷(Payload)和签名(Signature)。

  • 头部(Header):声明了JWT的类型(通常是JWT)以及所使用的加密算法(例如HMAC SHA256或RSA)

  • 载荷(Payload):承载实际数据的部分,可以包含预定义的声明(如iss(签发者)、exp(过期时间)、sub(主题)等)以及其它自定义的数据。这些信息都是铭文的,但不建议存放敏感信息。

  • 签名(Signature):通过对前两部分进行编码后的信息,使用指定的密钥通过头部(Header)中声明的加密算法生成,拥有验证数据完整性和防止篡改。

3、JWT的常规认证流程

2020040121153580.png

       JWT的认证流程如上图。当用户登录时,服务器通过验证用户名和密码后,会生成一个JWT,并将其发送给客户端。这个JWT中可能包含用户的认证信息、权限信息以及其它必要的业务数据。

       客户端在接收到JWT后,通常将其保存在本地(如Cookie、LocalStorage或者SessionStorage)。

       客户端在后续的请求中,携带此JWT(通常是附在HTTP请求头中),无需再次提交用户名和密码。服务器只需对收到的JWT进行解码并验证签名,即可完成用户身份的确认和权限验证。

4、JWT的完整认证流程

       在上面的JWT常规认证流程中,我们可以正常完成登陆、鉴权等认证,但是你会发现在这个流程中,我们无法实现退出登陆。

       当服务端将JWT发放给客户端后,服务端就失去了对JWT的控制权,只能等待这些发放出去的JWT超过有效期,自然失效。

       为了解决这个问题,我们引入了缓存,如下图。

2020040121022176.png

       当服务端生成JWT之后,在返回给客户端之前,先将JWT存入缓存中。要鉴权的时候,需要检验缓存中是否存在这个JWT。

       这样的话,如果用户退出登陆,我们只需要将缓存中的JWT删除,即可保证发放出去的JWT无法再通过鉴权。

5、JWT的优势与挑战

       JWT的主要优点在于无状态性,服务器无需存储会话状态,减轻了服务器压力,同时提高了系统的可扩展性和性能。

       此外,由于JWT的有效期限制,增强了安全性。

       然而,JWT也面临一些挑战,比如密钥的安全保管、JWT过期策略的设计以及如何处理丢失或被盗用的情况。

       因此,在实际应用中,需要综合考虑业务场景和技术特性来合理运用JWT。

6、JWT示例

       概念讲完了,我们最后来看个实例吧。

 // Java代码示例
    import io.jsonwebtoken.Jwts;
    import io.jsonwebtoken.SignatureAlgorithm;

    // 假设有一个User类,其中包含用户ID
    public class User {
        private String id;
        // 其他属性和方法...
    }

    // 创建JWT
    public String generateJWT(User user) {
        // 设置秘钥(在此处使用的是HMAC SHA-256算法)
        String secret = "your-secret-key"; // 在实际场景中应当从安全的地方获取秘钥
        long ttlMillis = 60 * 60 * 1000; // JWT的有效期为1小时

        // 构建载荷,包含用户ID和其他相关信息
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", user.getId());
        claims.put("exp", System.currentTimeMillis() + ttlMillis); // 设置过期时间

        // 生成JWT
        String jwt = Jwts.builder()
                .setClaims(claims)
                .signWith(SignatureAlgorithm.HS256, secret.getBytes(StandardCharsets.UTF_8))
                .compact();
        // TODO JWT写入缓存
        return jwt;
    }

    // 验证JWT
    public boolean validateJWT(String jwtToken, String secretKey) {
        boolean flag = false;
        try {
            Jwts.parser().setSigningKey(secretKey.getBytes(StandardCharsets.UTF_8)).parseClaimsJws(jwtToken);
            // 如果没有抛出异常,则JWT验证通过
            flag = true;
        } catch (ExpiredJwtException e) {
            // 如果Token过期
            System.out.println("JWT已过期");
        } catch (UnsupportedJwtException | MalformedJwtException | SignatureException | IllegalArgumentException e) {
            // 其他非法情况,如格式错误、签名无效等
            System.out.println("JWT验证失败:" + e.getMessage());
        }
        if (flag) {
            // TODO 校验缓存中是否有该JWT
        }
        return false;
    }

    // 使用示例
    public static void main(String[] args) {
        User user = new User("123"); // 假设这是合法用户的ID
        String token = generateJWT(user); // 生成JWT
        System.out.println("生成的JWT Token: " + token);

        // 验证生成的JWT
        boolean isValid = validateJWT(token, "your-secret-key");
        if (isValid) {
            System.out.println("JWT验证通过!");
        } else {
            System.out.println("JWT验证未通过!");
        }
    }

**MORE | 更多精彩文章**

  • 26
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

石头聊技术

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

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

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

打赏作者

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

抵扣说明:

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

余额充值