砍材农夫砍材农夫
  • 微信记账小程序
  • java
  • redis
  • mysql
  • 场景类
  • 框架类
  • vuepress搭建
  • hexo搭建
  • 云图
  • 常用工具

    • git
    • gradle
    • Zadig
    • it-tools
    • 开源推荐
    • curl
  • 大前端

    • nodejs
    • npm
    • webpack
    • 微信
    • 正则
    • uniapp
  • java

    • java基础
    • jdk体系
    • jvm
    • spring
    • spring_cloud
    • spring_boot
    • 分库分表
    • zookeeper
  • python

    • python基础
    • python高级
    • python框架
  • 算法

    • 算法
  • 网关

    • spring_cloud_gateway
    • openresty
  • 高可用

    • 秒杀
    • 分布式
    • 缓存一致
  • MQ

    • MQ
    • rabbitMQ
    • rocketMQ
    • kafka
  • 其它

    • 设计模式
    • 领域驱动(ddd)
  • 关系型数据库

    • mysql5.0
    • mysql8.0
  • 非关系型数据库

    • redis
    • mongoDB
  • 分布式/其他

    • ShardingSphere
    • 区块链
  • 向量数据库

    • M3E
    • OPEN AI
  • Jmeter
  • fiddler
  • wireshark
  • AI入门
  • AI大模型
  • AI插件
  • AI集成框架
  • 相关算法
  • AI训练师
  • 量化交易
  • gitee
  • github
  • infoq
  • osc
  • 砍材工具
  • 关于
  • 相关运营
  • docker
  • k8s
  • devops
  • nginx
  • 元宇宙
  • 区块链
  • 物联网
  • linux
  • webrtc
  • web3.0
  • gitee
  • github
  • infoq
  • osc
  • 砍材工具
  • 关于
  • 中考
  • 投资
  • 保险
  • 思
  • 微信记账小程序
  • java
  • redis
  • mysql
  • 场景类
  • 框架类
  • vuepress搭建
  • hexo搭建
  • 云图
  • 常用工具

    • git
    • gradle
    • Zadig
    • it-tools
    • 开源推荐
    • curl
  • 大前端

    • nodejs
    • npm
    • webpack
    • 微信
    • 正则
    • uniapp
  • java

    • java基础
    • jdk体系
    • jvm
    • spring
    • spring_cloud
    • spring_boot
    • 分库分表
    • zookeeper
  • python

    • python基础
    • python高级
    • python框架
  • 算法

    • 算法
  • 网关

    • spring_cloud_gateway
    • openresty
  • 高可用

    • 秒杀
    • 分布式
    • 缓存一致
  • MQ

    • MQ
    • rabbitMQ
    • rocketMQ
    • kafka
  • 其它

    • 设计模式
    • 领域驱动(ddd)
  • 关系型数据库

    • mysql5.0
    • mysql8.0
  • 非关系型数据库

    • redis
    • mongoDB
  • 分布式/其他

    • ShardingSphere
    • 区块链
  • 向量数据库

    • M3E
    • OPEN AI
  • Jmeter
  • fiddler
  • wireshark
  • AI入门
  • AI大模型
  • AI插件
  • AI集成框架
  • 相关算法
  • AI训练师
  • 量化交易
  • gitee
  • github
  • infoq
  • osc
  • 砍材工具
  • 关于
  • 相关运营
  • docker
  • k8s
  • devops
  • nginx
  • 元宇宙
  • 区块链
  • 物联网
  • linux
  • webrtc
  • web3.0
  • gitee
  • github
  • infoq
  • osc
  • 砍材工具
  • 关于
  • 中考
  • 投资
  • 保险
  • 思
  • 常见案例分析

    • 分布式ID
    • 分布式锁
    • 订单超时取消
    • 库存扣减问题
    • 幂等接口设计
    • 接口限流设计
    • 接口防刷设计
    • 多级缓存设计
  • 相关拓展知识

    • TCP和UDP区别
    • 签名算法
    • 身份认证令牌
    • 如何防止class类被反编译
    • 消息队列
    • maven如何统一指定jdk
    • maven常用插件
  • 算法|数据结构

    • 二叉树
    • 红黑树
    • 快速比较两棵树查找相同节点方法
  • 是什么?
  • 为什么需要令牌
  • 令牌的出现
  • 令牌三步走
  • 常见令牌
    • JWT(JSON Web Token)
      • jwt demo
    • OAuth2.0(不透明令牌)

是什么?

身份令牌是现代Web应用和移动应用中用于管理用户会话的核心机制

Image text

为什么需要令牌

没有令牌的世界——Cookie/Session(基于服务器存储的会话) 的传统模式

  • 你输入用户名密码登录。
  • 服务器验证通过,在服务器的内存里创建一个Session(会话记录),并生成一个对应的 Session ID(会话ID)。
  • 服务器把 Session ID 发给浏览器,浏览器存在 Cookie 里。
  • 以后每次请求,浏览器带上这个 ID。
  • 关键点:服务器收到 ID 后,必须去自己的内存(或数据库)里查找这个 Session 是否存在、是否过期

令牌的出现

无状态(Stateless)。服务器不再存储 Session,而是把用户信息(如用户ID、昵称、过期时间)经过加密,直接生成一个令牌交给客户端。 客户端每次带着这个令牌来,服务器只需要验证令牌本身的签名就能确认身份,无需查数据库或内存

令牌三步走

Image text

常见令牌

JWT(JSON Web Token)

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

JWT 由三部分组成:Header(头部)、Payload(负载)和Signature(签名)

  • 头部(Header):声明了加密算法(比如用了什么哈希算法)。
  • 载荷(Payload):存放实际数据的地方。比如用户ID(user_id: 123)、用户名、过期时间(exp)。注意:这里的数据只是用Base64编码(可解码看到原文),所以千万不要在JWT里存放密码等敏感信息。
  • 签名(Signature):这是最关键的防伪部分。服务器使用只有自己知道的密钥,对前两部分进行加密生成签名。如果有人篡改了令牌里的用户ID,签名就无法匹配,服务器会直接拒绝。
jwt demo
  <dependencies>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-api</artifactId>
            <version>0.11.5</version>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-impl</artifactId>
            <version>0.11.5</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-jackson</artifactId> <!-- 或 jjwt-gson,用于 JSON 处理 -->
            <version>0.11.5</version>
            <scope>runtime</scope>
        </dependency>
    </dependencies>
package com.jysemel;

import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;

import javax.crypto.SecretKey;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class JwtExample {

    // 生成一个足够安全的签名密钥(实际应用中应从配置文件读取或使用密钥库)
    private static final SecretKey SECRET_KEY = Keys.secretKeyFor(SignatureAlgorithm.HS256); // HS256 需要 256位密钥

    // 过期时间:1小时(毫秒)
    private static final long EXPIRATION_TIME = 3600000;

    public static void main(String[] args) {
        // 1. 生成 JWT
        String token = generateToken("user123", "admin");
        System.out.println("生成的 JWT:\n" + token);

        // 2. 验证并解析 JWT
        parseToken(token);
    }

    /**
     * 生成 JWT
     * @param subject  用户标识(如用户名、用户ID)
     * @param role     用户角色(自定义声明示例)
     * @return JWT 字符串
     */
    public static String generateToken(String subject, String role) {
        // 设置头部(可选,默认即可)
        Map<String, Object> header = new HashMap<>();
        header.put("typ", "JWT");

        // 设置载荷(Claims)
        JwtBuilder builder = Jwts.builder()
                .setHeader(header)                 // 头部
                .setSubject(subject)                // 主题(通常是用户标识)
                .setIssuedAt(new Date())            // 签发时间
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) // 过期时间
                .setIssuer("MyApp")                  // 签发者
                .setAudience("MyClient")             // 接收方
                .setId(java.util.UUID.randomUUID().toString()) // JWT ID,用于防止重放攻击
                .claim("role", role)                 // 自定义声明:角色
                .claim("dept", "engineering")        // 自定义声明:部门
                .signWith(SECRET_KEY);                // 签名

        return builder.compact();
    }

    /**
     * 解析 JWT,验证签名并提取数据
     * @param token JWT 字符串
     */
    public static void parseToken(String token) {
        try {
            // 创建解析器,设置签名密钥
            JwtParser parser = Jwts.parserBuilder()
                    .setSigningKey(SECRET_KEY)
                    .build();

            // 解析 JWT,得到 Jws<Claims> 对象
            Jws<Claims> jws = parser.parseClaimsJws(token);

            // 获取头部
            JwsHeader header = jws.getHeader();
            System.out.println("\n--- 解析结果 ---");
            System.out.println("算法:" + header.getAlgorithm());
            System.out.println("类型:" + header.getType());

            // 获取载荷
            Claims claims = jws.getBody();
            System.out.println("主题(subject):" + claims.getSubject());
            System.out.println("签发时间:" + claims.getIssuedAt());
            System.out.println("过期时间:" + claims.getExpiration());
            System.out.println("签发者:" + claims.getIssuer());
            System.out.println("接收方:" + claims.getAudience());
            System.out.println("JWT ID:" + claims.getId());
            System.out.println("角色(自定义声明):" + claims.get("role"));
            System.out.println("部门(自定义声明):" + claims.get("dept"));

        } catch (ExpiredJwtException e) {
            System.err.println("JWT 已过期:" + e.getMessage());
        } catch (UnsupportedJwtException e) {
            System.err.println("不支持的 JWT:" + e.getMessage());
        } catch (MalformedJwtException e) {
            System.err.println("JWT 格式错误:" + e.getMessage());
        } catch (SignatureException e) {
            System.err.println("JWT 签名验证失败:" + e.getMessage());
        } catch (IllegalArgumentException e) {
            System.err.println("JWT 参数非法:" + e.getMessage());
        }
    }
}

OAuth2.0(不透明令牌)

OAuth2.0 是一个开放授权标准,它允许用户授权第三方应用访问其资源,而无需将用户名和密码提供给第三方应用。

  • OAuth 2.0 授权码模式流程图(时序图) Image text
  • OAuth 2.0 核心角色关系图 Image text
最近更新: 2026/3/10 21:03
Contributors: kcnf
Prev
签名算法
Next
如何防止class类被反编译