百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术笔记 > 正文

JWT实现单点登录问题

dianpule 2025-05-15 17:30 8 浏览

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

通俗的解释:JWT简称 JSON Web Token,也就是JSON形式作为Web应用中的令牌信息,用于在各方之间安全的将信息作为JSON对象传输,在数据传输过程中可以完成数据加密,签名等操作。

session认证

我们最先接触到的认证方式就是基于Session的认证方式,每一个会话在服务端都会存储在HttpSession中,相当于一个Map,然后通过Cookie的形式给客户端返回一个jsessionid,然后每次访问的时候都需要从HttpSession中根据jsessionid来获取,通过这个逻辑来判断是否是认证的状态。

Session认证虽然是常见且有效的身份验证和会话管理机制,但也存在一些潜在的弊端问题:

  1. 服务器端存储开销:每个活跃会话都需要在服务器端存储会话数据,这可能会占用服务器资源,特别是在用户量较大或会话数据较大的情况下会造成OOM。
  2. 扩展性问题:随着用户量的增加,服务器端会话存储的管理和扩展可能变得复杂。需要考虑如何处理负载均衡、高可用性和容错等问题。
  3. 会话劫持风险:如果会话标识符未经充分保护,攻击者可能会通过各种手段(如会话劫持、会话固定攻击)获取合法用户的会话,从而冒充用户。
  4. 跨站点请求伪造(CSRF)攻击:虽然Session认证本身不直接防止CSRF攻击,但可以结合其他技术(如CSRF Token)来增强安全性。如果未正确实施,会增加应用程序的安全风险。
  5. 会话管理复杂性:管理会话的过期、续期和注销过程可能会变得复杂,尤其是在多个设备和会话的情况下。
  6. 移动设备和API的兼容性:对于移动设备和API,通常需要额外的考虑,以确保会话管理的安全性和效率。
  7. 单点故障:如果会话存储在单个服务器或单个数据中心,并且该服务器或数据中心发生故障,则可能导致所有用户的会话失效或不可用。

基于JWT的认证


认证的流程:

  • 用户通过表单把账号密码提交到后端服务后,如果认证成功就会生成一个对应的Token信息
  • 之后用户请求资源都会携带这个Token值,后端获取到后校验通过放行,校验不通过拒绝

jwt的优势:

  • 简介:可以通过URL,POST参数或者HTTP header发送,因为数据量小,传输速度快。
  • 自包含:负载中包含了所有用户所需的信息,避免多次查询数据
  • 夸语音:以JSON形式保存在客户端。
  • 不需要服务端保存信息,适合分布式环境。

jwt组成

jwt令牌的组成:

  • 标头(Header)
  • 有效载荷(Payload)
  • 签名(Signature)

因此JWT的格式为: xxxx.yyyy.zzzz Header.Payload.Signature

Header:

header通常由两部分组成:令牌的类型【JWT】和所使用的签名算法。例如HMAC、SHA256或者RSA,它会使用 Base64 编码组成 JWT结构的第一部分。注意:Base64是一种编码,是可以被翻译回原来的样子的。

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

Payload:

令牌的第二部分是有效负载,其中包含声明,声明是有关实体(通常是用户信息)和其他数据的声明,它会使用Base64来编码,组成JWT结构的第二部分。

Bash
{
	"userId":"123444",
	"userName":"yulang",
	"admin":true
}

注意:载体中的数据只是进行了base64编码,所以在使用的时候需要注意下不用存放敏感的数据。

Signature

签名部分,前面两部分都是使用 Base64 进行编码的,即前端可以解开header和payload中的信息,Signature需要使用编码后的 header 和 payload 以及我们提供的一个秘钥,然后使用 header 中指定的前面算法(HS256) 进行签名,签名的作用是保证 JWT 没有被篡改过

代码实现:

/**
     * 生成Token信息
     */
    public static String createToken(String userId) {

        // 使用 HMAC SHA-256 算法生成密钥
        Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256);

        String jws = Jwts.builder()
                .setSubject("yulang-token")
                .claim("userId", userId)
                .setExpiration(new Date(System.currentTimeMillis() + 3600000)) // 1小时后过期
                .signWith(key)
                .compact();

        return jws;
    }

根据Token来验证是否正确。

    public static String parseToken(String token) {

        // 使用 HMAC SHA-256 算法生成密钥
        Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256);

        Claims claims = Jwts.parserBuilder()
                .setSigningKey(key)
                .build()
                .parseClaimsJws(token)
                .getBody();

        System.out.println("Subject: " + claims.getSubject());
        System.out.println("Expiration: " + claims.getExpiration());

        return claims.get("userId")+ "";
    }

要让拦截器生效我们还需要添加对应的配置类。

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new JWTInterceptor())
                .addPathPatterns("/queryUser") // 需要拦截的请求
                .addPathPatterns("/saveUser") // 需要拦截的请求
                .excludePathPatterns("/login"); // 需要排除的请求
    }
}

登录使用:

    @PostMapping
    public String login(@RequestBody @Validated LoginDTO loginDTO) {
        // 业务操作 校验用户 密码
        User user = new User();
        user.setUserName(loginDTO.getUsername());
        user.setUserId("11000");
        String token = TokenUtil.createToken(user.getUserId());
        stringRedisTemplate.opsForValue().set(user.getUserId(), JSONUtil.toJsonStr(user));
        return token;
    }

验证


验证获取登录后的数据:

   @GetMapping("/index")
    public User index() {
        // 业务操作 校验用户 密码
        return UserInfoHolderUtil.get();
    }

相关推荐

TensorBoard最全使用教程:看这篇就够了

机器学习通常涉及在训练期间可视化和度量模型的性能。有许多工具可用于此任务。在本文中,我们将重点介绍TensorFlow的开源工具套件,称为TensorBoard,虽然他是TensorFlow...

用于图像降噪的卷积自编码器(自编码器和卷积自编码器)

这篇文章的目的是介绍关于利用自动编码器实现图像降噪的内容。在神经网络世界中,对图像数据进行建模需要特殊的方法。其中最著名的是卷积神经网络(CNN或ConvNet)或称为卷积自编码器。并非所有的读者都了...

Dropout和标准化(Batch Normalization)

1.介绍深度学习的世界不仅仅是致密层。有几十种类型的层可以添加到模型中(尝试浏览Keras文档以获取示例!)有些像致密层,定义了神经元之间的联系,有些则可以进行预处理或其他类型的转换。这儿,我们将介绍...

TensorFlow和Keras入门必读教程(keras与tensorflow的关系)

导读:本文对TensorFlow的框架和基本示例进行简要介绍。作者:本杰明·普朗什(BenjaminPlanche)艾略特·安德烈斯(EliotAndres)来源:华章科技01TensorFlo...

Keras各种Callbacks介绍(keras.regularizers)

1前言在tensorflow.keras中,callbacks能在fit、evaluate和predict过程中加入伴随着模型的生命周期运行,目前tensorflow.keras已经构建了许多种ca...

PHP防火墙代码,防火墙,网站防火墙,WAF防火墙,PHP防火墙大全

PHP防火墙代码,防火墙,网站防火墙,WAF防火墙,PHP防火墙大全资源宝整理分享:https://www.htple.netPHP防火墙(作者:悠悠楠杉)验证测试,链接后面加上?verify_cs=...

Android 开机启动流程分析(03)init启动关键进程uevent&watchdog

本章关键点总结&说明:说明:思维导图是基于之前文章不断迭代的,本章内容我们关注uevent&watchdog部分即可1Uevent入口Uevent是接收uevent的守护进程,这里它的主要作...

M1911半自动手枪:百年经典的枪械传奇

提到现代手枪的里程碑设计,M1911无疑是一个绕不开的名字。这款由约翰·勃朗宁(JohnBrowning)设计的手枪不仅在军用领域展现出卓越的性能,还深刻影响了后世枪械的发展。今天,我们来一同回顾M...

一文读懂 | coredump文件是如何生成的

人都会犯错,所以在编写程序时难免会出现BUG。有些BUG是业务逻辑上的错误导致的,一般不会导致程序崩溃,例如:原本要将两个数相加,但不小心把这两个数相减,而导致结果出错。这时我们可以通过在程序中...

kubernetes pod为什么需要pause容器?

当我们检查kubernetes集群的node节点时,我们使用dockerps查看时会发现一些名为pause的容器在节点上运行。$dockerpsCONTAINERIDIMA...

剖析Kubernetes中的Pause容器(kubernetes pause容器)

引言Kubernetes出现的报错如下:Failedtocreatepodsandbox:rpcerror:code=Unknowndesc=failedtogetsan...

深刻理解 Linux 进程间七大通信(IPC)

前言网络编程是LinuxC/C++的面试重点,今天我就来聊一聊进程间通信的问题,文章末尾列出了参考资料,希望帮助到大家。篇幅有点长,希望大家耐心阅读。Linux下的进程通信手段基本上是从Uni...

Linux应用开发之服务器的设计(linux服务器使用)

对于使用socket的网络服务器程序,有两种常见的设计方式:迭代型:服务器每次只处理一个客户端,只有当完全处理完一个客户端的请求后才去处理下一个客户端并发型:能够同时处理多个客户端的请求1.1、代...

C语言signal处理的底层机制深度探讨

在C语言中,signal处理是操作系统级别的事件处理机制,用于响应各种系统级事件,如程序错误、硬件中断等。深入理解signal处理的底层原理、使用方法以及其局限性对于编写稳定、可靠和安全的代码至关重要...

本文帮你在Unix上玩转C语言(unix语句)

shell是一种特殊的应用程序(命令行解释器),他为运行其他应用程序提供了一个接口。posix规范了操作系统是什么样每个进程都有一个工作目录(又叫当前目录),相对路径都是从工作目录开始解释。Ctrl+...