楼主: 正大1688
130 0

[学科前沿] 从“记住登录“到JWT:一文看懂Web认证技术的演进与实战 [推广有奖]

  • 0关注
  • 0粉丝

等待验证会员

学前班

80%

还不是VIP/贵宾

-

威望
0
论坛币
0 个
通用积分
0
学术水平
0 点
热心指数
0 点
信用等级
0 点
经验
30 点
帖子
2
精华
0
在线时间
0 小时
注册时间
2018-10-3
最后登录
2018-10-3

楼主
正大1688 发表于 2025-11-26 17:43:19 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币

从"记住登录"到JWT:深入理解Web认证技术的演进与实践

一、HTTP协议的本质:无记忆的通信机制

每当用户访问一个网站时,背后起作用的是HTTP协议。该协议具有“无状态”特性——这意味着每一次请求都是独立事件,服务器不会自动保留任何关于之前交互的信息。

这就像去便利店购买饮料,每次交易都彼此无关,店员并不记得你上个月买过什么。同样地,在网页通信中,每个请求对服务器而言都是一次全新的对话。

https://
http://

二、如何在多次请求间识别用户身份

当用户完成登录操作后,系统必须能够在后续的多个请求中持续识别其身份。为此,诞生了会话跟踪技术,旨在解决HTTP无状态带来的身份识别难题。

Part1:基于Cookie的身份标识机制

工作原理

服务器通过响应头将数据写入用户的浏览器(如Set-Cookie),这些数据即为Cookie。之后,浏览器会在每次向同一域名发起请求时,自动携带Cookie信息(通过Cookie请求头)回传给服务器。

Set-Cookie
user_id=123
Cookie

典型应用场景

  • 自动填充用户名
  • 临时保存购物车内容
  • 验证码状态维持

存在的局限性

  • 用户可手动禁用Cookie,导致功能异常
  • 部分移动端APP环境不支持Cookie机制
  • 无法实现跨域共享:不同协议、IP/域名或端口之间无法共用Cookie

例如,从https://a.example.com登录后跳转至https://b.example.com,由于属于不同子域,原有状态将丢失。

192.168.150.100:8080
192.168.150.20:90

判断是否跨域主要依据三个维度:

  • 协议(如http与https)
  • IP地址或域名
  • 端口号

Part2:Session机制——服务端维护会话数据

运行机制

用户成功登录后,服务器创建唯一的会话ID(Session ID),并通过Cookie发送给客户端。此后每次请求都会附带此ID,服务器根据ID查找存储在内存或数据库中的完整会话信息(如用户权限、登录时间等)。

SESS_abc123

典型问题场景

假设你在公司使用电脑登录内网系统,此时Session存储在服务器A上;第二天换到学校机房访问相同系统,请求被负载均衡分配至服务器B。由于各服务器未共享Session数据,系统无法识别你的身份,从而要求重新登录。

注意

这种现象常见于集群部署环境下,因Session未能同步而导致重复登录的问题。

Session

图示说明:尽管每次请求均包含Cookie,但由于跨域限制及服务器间数据不同步,仍需反复进行身份验证。

Part3:JWT令牌——现代主流认证方案

核心优势

  • 无状态设计:无需服务器保存会话信息
  • 天然支持跨域:适用于前后端分离架构
  • 适应集群部署:各节点可独立验证令牌
  • 多平台兼容:适用于PC网页、移动App等多种终端

JWT结构解析

JWT(JSON Web Token)是一个自包含的字符串令牌,由三部分组成,以点号分隔:

  1. Header(头部):声明令牌类型和签名算法(如HS256),经Base64Url编码
  2. Payload(负载):存放用户信息、过期时间等自定义声明
  3. Signature(签名):使用密钥对前两部分加密生成,确保令牌不可篡改

为何选择JWT?

  • 支持分布式部署:无需在多个服务器间同步Session数据,每个节点均可独立校验令牌有效性
  • 良好的跨域能力:适合前端(如Vue/React)与后端分离开发模式
  • 降低服务端存储压力:所有必要信息已嵌入令牌本身,无需频繁查询数据库
  • 全平台通用:无论是Web、iOS还是Android应用,均可统一采用JWT进行认证

注:虽然JWT具备诸多优点,但也需要开发者自行实现令牌刷新、黑名单管理等功能,属于“手动化”程度较高的方案。

Vue
SpringBoot

实战案例:Tlias项目中的JWT集成

一、环境搭建

若使用Maven构建项目,请在项目的pom.xml文件中添加以下依赖项:

pom.xml
jjwt
<dependencies>
  <!-- JJWT API -->
  <dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-api</artifactId>
    <version>0.11.5</version>
  </dependency>
  <!-- JJWT 实现 -->
  <dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-impl</artifactId>
    <version>0.11.5</version>
    <scope>runtime</scope>
  </dependency>
  <!-- JJWT Jackson 支持(用于 JSON 处理) -->
  <dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-jackson</artifactId>
    <version>0.11.5</version>
    <scope>runtime</scope>
  </dependency>
</dependencies>

二、编写JWT工具类

代码详解

1. 密钥生成

为保证安全性,需使用强随机密钥进行签名。推荐使用HS256算法配合至少256位长度的密钥。

2. 令牌有效期设置

合理设定过期时间(如30分钟),避免长期有效带来的安全风险。可通过exp声明控制失效时间。

3. 生成令牌

将用户基本信息(如ID、角色)写入Payload,并结合密钥生成完整的JWT字符串返回给客户端。

4. 解析令牌

接收客户端传来的JWT,验证签名有效性并提取其中的Payload数据,用于权限判断和身份识别。

完整代码示例

(此处省略具体Java实现代码,实际开发中应封装成工具类提供统一接口)

收获总结

通过本篇内容的学习,我们了解了从传统Cookie/Session到现代JWT的认证技术演进路径:

  • Cookie解决了基础的数据存储问题,但受限于浏览器策略和跨域障碍
  • Session增强了安全性,却带来了服务器状态依赖和扩展难题
  • JWT以其无状态、易扩展、跨平台等优势,成为当前企业级系统的首选方案

结语

尽管目前纯Cookie/Session方式在实际生产环境中已逐渐被替代,但在高校教学和考试中仍常作为基础知识讲解。对于希望掌握前沿技术的开发者来说,直接聚焦JWT及相关生态是更高效的学习路径。

掌握JWT不仅意味着学会一种认证手段,更是理解现代分布式系统设计理念的重要一步。

<artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
</dependencies>

请依据最新版本进行配置调整。

jjwt

开发环境准备

确保已正确配置 JDK 开发环境,以支持后续的 JWT 功能实现。

二、JWT 工具类设计与实现

我们将构建一个工具类用于生成和解析 JWT 令牌。以下为具体代码结构及详细说明。

JwtUtils

1. 密钥生成机制

采用如下方式初始化签名密钥:

private static final SecretKey SECRET_KEY = Keys.secretKeyFor(SignatureAlgorithm.HS256);

通过 Keys.secretKeyFor 方法自动生成符合 HS256 算法安全标准的密钥。

注意:在生产环境中,应避免将密钥直接硬编码在源码中,推荐使用环境变量或专用密钥管理服务进行安全管理。

Keys.secretKeyFor

2. 设置令牌有效期

定义常量控制令牌有效时长:

private static final long EXPIRATION_TIME = 24 * 60 * 60 * 1000L; // 24小时

可根据实际业务需求灵活调整该时间值。

3. 生成 JWT 令牌

核心方法签名如下:

public static String generateToken(Map<String, Object> claims)

功能描述:基于传入的键值对数据(如用户ID、用户名等)生成加密的 JWT 字符串。

执行流程

  • 利用 Jwts.builder() 初始化一个 JWT 构建器实例;
  • 调用 .addClaims(claims) 添加自定义声明内容至 Payload 区域;
  • 通过 .signWith(SECRET_KEY, SignatureAlgorithm.HS256) 指定签名算法与密钥,保障令牌完整性;
  • 设置过期时间戳:.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
  • 最终调用 .compact() 方法完成 JWT 的序列化输出。
Jwts.builder()
addClaims(claims)
signWith(SECRET_KEY, SignatureAlgorithm.HS256)
setExpiration(...)
compact()

4. 解析并验证 JWT 令牌

对应解析方法定义如下:

public static Claims parseToken(String token) throws Exception

功能说明:对接收到的 JWT 字符串进行解码与校验,返回包含原始声明信息的 Claims 对象。

处理步骤

  • 使用 Jwts.parserBuilder() 创建解析器构造器;
  • 通过 .setSigningKey(SECRET_KEY) 配置用于验证签名的密钥;
  • 调用 .build() 完成解析器实例构建;
  • 执行 .parseClaimsJws(token) 对令牌进行完整验证(包括格式、签名、时效性等);
  • 若验证成功,则提取其中的载荷部分,并通过 .getBody() 获取封装了所有自定义信息的 Claims 实例。

一旦令牌无效、过期或签名不匹配,系统将抛出相应异常,需由上层逻辑捕获处理。

Claims
Jwts.parserBuilder()
setSigningKey(SECRET_KEY)
build()
parseClaimsJws(token)
getBody()
Claims

完整工具类代码

package com.example.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import javax.crypto.SecretKey;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class JwtUtils {

    // 使用 HS256 算法生成的安全密钥
    // 注意:生产环境下请勿硬编码密钥,建议从外部配置加载
    private static final SecretKey SECRET_KEY = Keys.secretKeyFor(SignatureAlgorithm.HS256);

    // 设定令牌有效时间为 24 小时(毫秒)
    private static final long EXPIRATION_TIME = 24 * 60 * 60 * 1000L; // 24小时

    /**
     * 生成 JWT 令牌
     *
     * @param claims 包含用户相关信息的键值对集合
     * @return 返回生成的 JWT 字符串
     */
    public static String generateToken(Map<String, Object> claims) {
        return Jwts.builder()
                .addClaims(claims)
                .signWith(SECRET_KEY, SignatureAlgorithm.HS256)
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
                .compact();
    }

    /**
     * 解析并验证 JWT 令牌
     *
     * @param token 待解析的 JWT 字符串
     * @return 解析成功的声明对象
     * @throws Exception 若令牌无效、过期或签名错误则抛出异常
     */
    public static Claims parseToken(String token) throws Exception {
        return Jwts.parserBuilder()
                .setSigningKey(SECRET_KEY)
                .build()
                .parseClaimsJws(token)
                .getBody();
    }
}
// 设置令牌过期时间
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
// 生成并返回紧凑格式的 JWT 字符串
.compact();
}

/**
 * 解析 JWT 令牌
 *
 * @param token 需要解析的 JWT 令牌字符串
 * @return 包含令牌数据的 Claims 对象
 * @throws Exception 当令牌无效、已过期或签名验证失败时抛出异常
 */
public static Claims parseToken(String token) throws Exception {
    return Jwts.parserBuilder()
        // 指定签名所用的密钥
        .setSigningKey(SECRET_KEY)
        // 创建 JWT 解析器实例
        .build()
        // 解析传入的令牌并进行校验
        .parseClaimsJws(token)
        // 提取 Payload 中的声明信息(Claims)
        .getBody();
}

收获总结

通过本文的学习,已经基本掌握了三种持续演进的 Web 认证方式,深入理解了当前较为流行的 JWT 技术。该技术具备良好的无状态性与扩展性,适用于现代分布式系统的身份验证场景,可直接应用于实际开发项目中。

结语

本文由初学者编写,内容可能存在疏漏或错误之处,恳请各位经验丰富的朋友不吝指正,以便持续改进和完善。

二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:认证技术 WEB JWT signature Algorithm

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
扫码
拉您进交流群
GMT+8, 2026-2-11 01:20