首页 > 其他分享 >我不应该用JWT的!

我不应该用JWT的!

时间:2024-07-15 17:35:07浏览次数:9  
标签:username jwt JWT Redis token 应该 String

一、前言

大家好呀,我是summo,之前有自学过Shrio框架,网上一搜就有SpringBoot整合Shrio+ JWT的文章,我是在学习Shrio框架的时候顺带学的JWT。后来我还看见有很多博主专门写文章介绍JWT,说这个东西的优点很多,安全性好、去中心化、方便啥的,我就把JWT也应用在我们自己的系统中了。但最近发现这玩意越来越让我觉得别扭,总感觉哪里不太对劲,重新审查我的登录认证逻辑之后才发现:我不应该用JWT的!

这里我用一句解释不该用的原因,省得浪费大家的时间:我的系统有Redis,而且还用Redis存了JWT,随着系统升级,JWT越来越像普通Token!
明白原理的同学可能心中暗笑,直接跳过看下一篇了,不明白原理的同学,可以看看这个四不像是怎么被我搭出来的。

二、JWT是什么?

看我文章的有很多大神,也有一些小白,所以为了不让小白们看的云里雾里,我还是有必要介绍一些基本原理。JWT是 JSON Web Token 的缩写,可以对JSON对象进行编码(加密),并通过这个编码传递信息。

1. JWT的结构

(1)头部(Header)

头部通常由两部分组成,即令牌的类型(typ)和所使用的算法(alg)。例如,一个头部可能是 {"alg": "HS256", "typ": "JWT"},表示使用 HMAC SHA-256 算法对令牌进行签名。

(2)载荷(Payload)

载荷包含了 JWT 的声明信息,用于描述令牌的相关内容。载荷可以包含标准声明(例如:发行者、主题、过期时间等),也可以包含自定义声明。例如,一个载荷可能是 {"sub": "1234567890", "name": "John Doe", "exp": 1516239022}。

(3)签名(Signature)

签名用于验证令牌的完整性和真实性。签名通常由头部、载荷和密钥一起计算而得。验证者可以使用相同的密钥重新计算签名,并将结果与令牌中的签名进行比较,以确认令牌的真实性。

2. SpringBoot使用JWT

(1)maven引入

<!-- jwt -->
<dependency>
  <groupId>com.auth0</groupId>
  <artifactId>java-jwt</artifactId>
  <version>3.8.2</version>
</dependency>

(2)代码示例


import java.util.Date;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

@Slf4j
public class JWTUtil {
    /**
     * 过期时间
     */
    private static final long EXPIRE_TIME = 60 * 1000;

    /**
     * 校验 token是否正确
     *
     * @param token  密钥
     * @param secret 用户的密码
     * @return 是否正确
     */
    public static boolean verify(String token, String username, String secret) {
        try {
            Algorithm algorithm = Algorithm.HMAC256(secret);
            JWTVerifier verifier = JWT.require(algorithm)
                .withClaim("username", username)
                .build();
            verifier.verify(token);
            log.info("token is valid");
            return true;
        } catch (Exception e) {
            log.info("token is invalid{}", e.getMessage());
            return false;
        }
    }

    /**
     * 从 token中获取用户名
     *
     * @return token中包含的用户名
     */
    public static String getUsername(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim("username").asString();
        } catch (JWTDecodeException e) {
            log.error("error:{}", e.getMessage());
            return null;
        }
    }

    /**
     * 生成 token
     *
     * @param username 用户名
     * @param secret   用户的密码
     * @return token
     */
    public static String sign(String username, String secret) {
        try {
            username = StringUtils.lowerCase(username);
            Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
            Algorithm algorithm = Algorithm.HMAC256(secret);
            return JWT.create()
                .withClaim("username", username)
                .withExpiresAt(date)
                .sign(algorithm);
        } catch (Exception e) {
            log.error("error:{}", e);
            return null;
        }
    }

    public static void main(String[] args) {
        //对数据进行加密
        String token = sign("zhangshan", "123456");
        System.out.println(token);
        //对数据进行解密
        System.out.println(getUsername(token));
    }
}

运行一下

JWT还是很简单的,一学就会,很多博主在介绍它的时候都会说它安全、方便、去中心化等等,然后强烈推荐大家使用。但这里我要就要给大家泼冷水了,学是肯定要学的,用就需要看情况了,不能别人说它好,你就无脑用,然后用成一个四不像。至于我为什么说我用来是四不像,接着看!

三、JWT vs Token+Redis

在设计no session系统时,有两种可选方案:JWT与Token+Redis。

1. 原理简介

  • JWT: 生成并发给客户端之后,后台是不用存储,客户端访问时会验证其签名、过期时间等再取出里面的信息(如username),再使用该信息直接查询用户信息完成登录验证。jwt自带签名、过期等校验,后台不用存储,缺陷是一旦下发,服务后台无法拒绝携带该jwt的请求(如踢除用户);

  • Token+Redis: 是自己生成个32位的key,value为用户信息,访问时判断redis里是否有该token,如果有,则加载该用户信息完成登录。服务需要存储下发的每个token及对应的value,维持其过期时间,好处是随时可以删除某个token,阻断该token继续使用。

2. 两种方案的优缺点

(1)去中心化的JWT

优点

  1. 去中心化,便于分布式系统使用
  2. 基本信息可以直接放在token中。 username,nickname,role
  3. 功能权限较少的话,可以直接放在token中。用bit位表示用户所具有的功能权限

缺点

  1. 服务端不能主动让token失效

(2)中心化的Redis+Token

优点

  1. 服务端可以主动让token失效

缺点

  1. 依赖内存或redis存储。
  2. 分布式系统的话,需要redis调用增加了系统复杂性。

光看优缺点的话,JWT优点还比Redis+Token多,在小白时期的我一看:好家伙,JWT这么多优点,用它准没错,看来简历上又可以加上一笔了!

四、我的方案

想法是美好的,但现实是残酷的,为什么我会觉得越来越别扭,先上一张流程图,让大家看看我在业务中是怎么做的,如下:

上面的方案是JWT或者Redis+Token,而我的方案是JWT+Redis

标签:username,jwt,JWT,Redis,token,应该,String
From: https://www.cnblogs.com/wlovet/p/18303453

相关文章

  • 2024-07-15 vue组件发布npm后,再使用,样式不见了?==》查看样式是否在dist包里,有的话应
    哎,嗯。。。emmm。。。好,问题就是这样的,最近写了vue组件打算上到npm,然后上是上了,但是样式却没有生效??左上角是组件样式本地调试的截图,可以看到是生效的,右上角的截图是我在别的项目引用了我写的这个库,结果样式却没有生效。我打包后的文件列表如下: 注意:style.css包含了所有的样......
  • Ajax代码运行前应该先加载jQuery
    <scriptsrc="{%static'js/jquery-3.6.0.min.js'%}"></script><script>//使用jQuery获取分类列表并绑定点击事件,用于自动更新【博客分类】阅读$(document).ready(function(){$('#category-list').on('click','li',fun......
  • 在webapi中创建一个jwt token
    1.第一步首先创建一个webapi项目2.安装nuget包: Microsoft.AspNetCore.Authentication.JwtBearer3.,然后再Program.cs文件中添加 4.然后运行起来 5.打开jwt.io网站,解密token 关于:iss,sub,exp,iat,nbf更新信息看下图:  ......
  • 计算机科班生未来应该怎么选择
    选专业要了解自己的兴趣所在。即想要学习什么样的专业,如果有明确的专业意向,就可以有针对性地选择那些专业实力较强的院校。2.如果没有明确的专业意向,可以优先考虑一下院校。确定一下自己想要选择综合性院校还是理工类院校或是像财经或者语言之类的特色院校。3.综合考虑地区......
  • 常见的保护器件包括TVS管、自恢复保险丝、气体放电管和压敏电阻,使用这些器件时应该如
    在电子电路设计中,保护电路元件的选择和使用至关重要。无论是避免电源过压、静电放电(ESD)还是浪涌,保护器件都能有效保护电路,延长产品的使用寿命。本文将详细介绍几种常见的保护器件:TVS管、自恢复保险丝、气体放电管和压敏电阻,包括它们的工作原理、选择参数以及常用型号推荐。......
  • 【C#】MouseDown与MouseDoubleClick事件,如果此时双击,那么这俩事件的是否都响应?如果都
    问题描述MouseDown与MouseDoubleClick事件,如果此时双击,那么这俩事件的是否都响应?如果都响应,那么应该先执行那个方法?问题响应在WindowsForms或WPF等基于事件的GUI框架中,MouseDown和MouseDoubleClick是两个不同的鼠标事件。当双击鼠标时,这两个事件都可能被触发,但是它们的......
  • 忽然明白人的一生应该怎么度过:勇敢的追逐自己的梦想!
    人本不应该是劳碌一生,而在生命的尽头才幡然醒悟,自己的梦想总归需要自己去追逐。我的梦想:独立开发一款MMO网络游戏(使用Unity3D)目前困难:1、完全小白2、会一点编程基础,但是不能独立开发3、完全跨行业,目前本人从事某国企工程局财务工作,工作强度比较大4、没有共同的小伙伴,说白了......
  • 鸿蒙开发的语言应该怎么选?
    省流推荐ArkTS(支持HarmonyOSNext),放弃类JS开发方式,也不推荐仓颉鸿蒙开发的语言应该怎么选?在2024/06之前,官方文档【3.0/4.1】中尚有大篇幅的Web开发文档,并且在2019-2023年,每年的鸿蒙开发者大会上,多次提到过Web开发模式然而在2024年开发者大会上,官方不在提及这......
  • 使用Spring Boot和JWT实现安全认证
    使用SpringBoot和JWT实现安全认证大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!1.什么是JWT?JSONWebToken(JWT)是一种开放标准(RFC7519),定义了一种紧凑且独立的方式,可以在各方之间作为JSON对象安全地传输信息。在Web开发中,JWT通常用于跨域认证和授权,特......
  • Java token穷举id造假 jwt token伪造
    一、JWT简介1、简介JSONWebToken(JSONWeb令牌)是一个开放标准(rfc7519),它定义了一种紧凑的、自包含的方式,用于在各方之间以JSON对象安全地传输信息。通过JSON形式作为Web应用中的令牌,用于在各方之间安全地将信息作为JSON对象传输。在数据传输过程中还可以完成数据 加密、签名......