最新资讯

  • JavaToken实战指南:从原理到应用

JavaToken实战指南:从原理到应用

2026-02-04 21:26:35 栏目:最新资讯 4 阅读

好的,这是一份非常详细、实用、通俗易懂、权威且全面的 Java Token 全面指南。我们将从基础概念开始,逐步深入,涵盖原理、实战代码和完整的系统案例。


Java Token 全面指南:从原理到实战

目录

  1. 什么是 Token? 1.1 概念与类比 1.2 在 Java 环境中的核心作用 1.3 常见 Token 类型概述
  2. Java 源码解析:编译器视角下的 Token 2.1 词法分析 (Lexical Analysis) 基础 2.2 Java 语言的 Token 类型详解 2.3 实战:使用 StringTokenizer (基础解析) 2.4 实战:使用正则表达式 PatternMatcher (灵活解析) 2.5 实战:手动实现简易词法分析器 (理解原理)
  3. 身份认证与授权:安全领域的 Token (JWT 为例) 3.1 认证 (Authentication) 与授权 (Authorization) 基础 3.2 为什么需要 Token (Session 的局限) 3.3 JWT (JSON Web Token) 深入解析 3.3.1 结构 (Header, Payload, Signature) 3.3.2 签名算法与安全性 3.3.3 优点与适用场景 3.3.4 安全注意事项 3.4 实战:使用 java-jwt 库创建和验证 JWT
  4. API 访问控制:OAuth 2.0 中的 Token 4.1 OAuth 2.0 框架简介 4.2 Access Token 与 Refresh Token 4.2.1 作用与生命周期 4.2.2 最佳安全实践 4.3 实战:模拟 OAuth 2.0 授权服务器颁发 Token (简化版) 4.4 实战:资源服务器验证 Access Token (简化版)
  5. 令牌化 (Tokenization) 与敏感数据处理 5.1 令牌化概念 (非认证 Token) 5.2 应用场景:支付卡信息 (PCI DSS)、个人身份信息 (PII) 保护 5.3 与加密的区别 5.4 实战:简易支付卡令牌化系统示例
  6. 系统案例:综合应用 6.1 案例一:Java 源码关键词提取工具 6.2 案例二:基于 JWT 的 RESTful API 用户认证系统 6.3 案例三:简易 OAuth 2.0 受保护的资源访问系统

1. 什么是 Token?

1.1 概念与类比

想象一下你进入一个高档俱乐部。门卫不会每次都检查你的详细资料(姓名、住址、职业等),而是查看你的会员卡。这张会员卡就是一个 Token。它代表了你已经被验证过的身份和拥有的权限(比如进入特定区域)。在计算机世界中,Token 扮演着类似的角色:它是一种凭证代表物,用于表示身份、权限、状态或特定数据片段。

1.2 在 Java 环境中的核心作用

Token 在 Java 应用的多个层面发挥着关键作用:

  • 编译器层面: Java 源代码在编译前会被分解成更小的、有意义的单元,这些单元就是 Token(如关键字、标识符、运算符、字面量)。这是代码能被理解和执行的基础。
  • 安全层面: 用于用户身份认证(Authentication)和访问授权(Authorization)。例如,JWT (JSON Web Token) 是 RESTful API 中广泛使用的认证 Token。
  • API 交互层面: 在 OAuth 2.0 等授权框架中,Access Token 是客户端访问受保护资源的“钥匙”。
  • 数据安全层面: Tokenization(令牌化)用于保护敏感数据(如信用卡号),用无意义的 Token 代替原始数据存储,原始数据则安全地存放在其他地方。

1.3 常见 Token 类型概述

  • 词法 Token: int, "Hello", +, myVariable, ; (Java 编译过程使用)
  • 认证 Token: JWT, Opaque Token, SAML Token (用于验证用户身份)
  • 授权 Token: OAuth 2.0 Access Token, Refresh Token (用于授予访问权限)
  • 数据 Token: 代表原始敏感数据(如信用卡号)的随机字符串 (用于数据保护)

2. Java 源码解析:编译器视角下的 Token

当你在 IDE 中编写 Java 代码并点击运行时,Java 编译器 (javac) 首先会进行词法分析 (Lexical Analysis)。这一步将连续的字符流(你的源代码)分解成一系列有意义的词法单元 (Lexical Tokens) 或简称 Token。这是理解代码的第一步。

2.1 词法分析 (Lexical Analysis) 基础

词法分析器(也称为扫描器 Scanner)的工作:

  1. 读取: 逐个字符读取源代码。
  2. 分类: 根据 Java 语言规范,将字符序列组合成特定类型的 Token。
  3. 输出: 生成一个 Token 序列(流),供下一阶段的语法分析器 (Parser) 使用。

2.2 Java 语言的 Token 类型详解

Java 编译器识别的主要 Token 类型包括:

  • 关键字: 具有特殊含义的保留字。如 public, class, static, void, if, else, for, while 等。
  • 标识符: 由程序员定义的名称,用于变量、方法、类、接口等。如 myVariable, calculateSum, String, UserRepository。规则:以字母、_$ 开头,后可跟字母、数字、_$
  • 字面量: 直接在代码中写出的常量值。
    • 整数: 42, 0x2A, 0b101010
    • 浮点数: 3.14, 6.022e23
    • 字符: 'A', ' ', 'A'
    • 字符串: "Hello, World!"
    • 布尔值: true, false
    • null: null
  • 运算符: 用于执行操作的符号。如 +, -, *, /, %, =, ==, !=, <, >, <=, >=, &&, ||, !, ++, --, ?:, instanceof 等。
  • 分隔符: 用于分组代码或定义结构。如 (, ), {, }, [, ], ;, ,, .
  • 注释: // 单行注释, /* 多行注释 */, /** 文档注释 */ (虽然编译器最终可能忽略其内容,但词法分析器需要识别它们作为特定 Token)。

2.3 实战:使用 StringTokenizer (基础解析)

java.util.StringTokenizer 是一个相对古老但简单的类,用于将字符串分解成 Token。它默认根据空格、制表符、换行符、回车符进行分割。

import java.util.StringTokenizer;

public class StringTokenizerExample {
    public static void main(String[] args) {
        String javaCode = "public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, Token!"); } }";
        StringTokenizer tokenizer = new StringTokenizer(javaCode);

        System.out.println("Tokens extracted by StringTokenizer:");
        while (tokenizer.hasMoreTokens()) {
            String token = tokenizer.nextToken();
            System.out.println(token);
        }
    }
}

运行结果: 会按空格分割输出每个单词/符号。但请注意,它不会识别 Java 语法,只是简单地按空格分割。对于 String[] args 这样的部分,它会分割成 String[]args

2.4 实战:使用正则表达式 PatternMatcher (灵活解析)

正则表达式提供了更强大的模式匹配能力,可以用来定义更复杂的 Token 规则。

import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class RegexTokenExample {
    public static void main(String[] args) {
        String javaCode = "int sum = 100 + 200; // Calculate total";
        // 一个简单的正则,匹配:标识符、关键字、数字、运算符、注释
        // 注意:这个正则非常简化,仅用于示例,不能覆盖所有Java语法
        String regex = "(//.*)|("[^"]*")|(d+)|(w+)|([=+;])";

        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(javaCode);

        System.out.println("Tokens extracted by Regex:");
        while (matcher.find()) {
            String token = matcher.group().trim();
            if (!token.isEmpty()) { // 忽略空匹配
                System.out.println("Found token: '" + token + "'");
            }
        }
    }
}

运行结果: 可能会匹配出 int, sum, =, 100, +, 200, ;, // Calculate total。正则表达式提供了灵活性,但编写一个能完美处理所有 Java 语法的正则极其复杂。

2.5 实战:手动实现简易词法分析器 (理解原理)

为了更深入理解编译器如何工作,我们可以手动实现一个非常简易的词法分析器,只处理部分 Token 类型(如标识符、整数、运算符)。

public class SimpleLexer {

    private final String input;
    private int position = 0; // 当前位置
    private char currentChar; // 当前字符

    public SimpleLexer(String input) {
        this.input = input;
        this.currentChar = input.length() > 0 ? input.charAt(0) : '';
    }

    // 前进一个字符
    private void advance() {
        position++;
        if (position < input.length()) {
            currentChar = input.charAt(position);
        } else {
            currentChar = ''; // 结束标记
        }
    }

    // 跳过空白字符
    private void skipWhitespace() {
        while (currentChar != '' && Character.isWhitespace(currentChar)) {
            advance();
        }
    }

    // 获取下一个 Token
    public Token getNextToken() {
        while (currentChar != '') {
            if (Character.isWhitespace(currentChar)) {
                skipWhitespace();
                continue;
            }

            if (Character.isLetter(currentChar)) { // 标识符或关键字
                return parseIdentifierOrKeyword();
            }

            if (Character.isDigit(currentChar)) { // 整数
                return parseInteger();
            }

            // 简单处理几个运算符
            if (currentChar == '=') {
                advance();
                return new Token(TokenType.ASSIGN, "=");
            }
            if (currentChar == '+') {
                advance();
                return new Token(TokenType.PLUS, "+");
            }
            if (currentChar == ';') {
                advance();
                return new Token(TokenType.SEMICOLON, ";");
            }

            // 无法识别,抛出错误 (简化处理)
            throw new RuntimeException("Unexpected character: " + currentChar);
        }
        return new Token(TokenType.EOF, "");
    }

    // 解析标识符或关键字
    private Token parseIdentifierOrKeyword() {
        StringBuilder result = new StringBuilder();
        while (currentChar != '' && (Character.isLetterOrDigit(currentChar) || currentChar == '_')) {
            result.append(currentChar);
            advance();
        }
        String value = result.toString();
        // 这里可以检查是否是关键字,简化处理都当作标识符
        return new Token(TokenType.IDENTIFIER, value);
    }

    // 解析整数
    private Token parseInteger() {
        StringBuilder result = new StringBuilder();
        while (currentChar != '' && Character.isDigit(currentChar)) {
            result.append(currentChar);
            advance();
        }
        return new Token(TokenType.INTEGER, result.toString());
    }

    // Token 类型枚举
    public enum TokenType {
        IDENTIFIER, INTEGER, ASSIGN, PLUS, SEMICOLON, EOF
    }

    // Token 类
    public static class Token {
        public final TokenType type;
        public final String value;

        public Token(TokenType type, String value) {
            this.type = type;
            this.value = value;
        }

        @Override
        public String toString() {
            return "Token(" + type + ", '" + value + "')";
        }
    }

    public static void main(String[] args) {
        String testInput = "x = 42 + y;";
        SimpleLexer lexer = new SimpleLexer(testInput);

        Token token;
        do {
            token = lexer.getNextToken();
            System.out.println(token);
        } while (token.type != TokenType.EOF);
    }
}

运行结果:

Token(IDENTIFIER, 'x')
Token(ASSIGN, '=')
Token(INTEGER, '42')
Token(PLUS, '+')
Token(IDENTIFIER, 'y')
Token(SEMICOLON, ';')
Token(EOF, '')

这个简易分析器展示了词法分析的基本流程:跳过空白、按字符类型分支、组合字符序列形成 Token。真实的编译器词法分析器要复杂得多,处理所有 Token 类型和边界情况。


3. 身份认证与授权:安全领域的 Token (JWT 为例)

3.1 认证 (Authentication) 与授权 (Authorization) 基础

  • 认证: 验证用户身份(你是谁?)。例如:用户名/密码登录、指纹识别。
  • 授权: 验证用户是否有权限执行某项操作(你能做什么?)。例如:管理员可以删除用户,普通用户只能查看。

3.2 为什么需要 Token (Session 的局限)

传统的 Web 应用常使用 Session 进行状态管理:

  1. 用户登录,服务器验证凭据。
  2. 服务器创建 Session(存储用户信息),生成一个唯一的 Session ID
  3. 服务器将 Session ID 通过 Cookie 返回给浏览器。
  4. 后续请求,浏览器自动带上 Cookie(含 Session ID)。
  5. 服务器根据 Session ID 查找 Session,获取用户状态。

Session 的局限性:

  • 服务器存储: Session 数据通常存储在服务器内存或数据库中。用户量大时,存储开销大。
  • 扩展性: 在分布式或微服务架构中,需要 Session 共享机制(如 Redis),增加了复杂性。
  • 移动端/API 友好性: 原生 App 或 API 客户端处理 Cookie 不如浏览器方便。
  • 跨域: Cookie 默认策略在跨域场景下受限。

Token 的优势 (如 JWT):

  • 无状态: Token 本身包含所需信息(如用户 ID、角色)。服务器无需存储会话状态,只需验证 Token 有效性(签名)。
  • 跨域/跨平台友好: Token 通常放在 HTTP Header (如 Authorization: Bearer ) 中传递,易于各种客户端处理。
  • 灵活性: 可以包含丰富的声明 (Claims)。
  • 标准化: JWT 是开放标准 (RFC 7519),各种语言都有成熟库支持。

3.3 JWT (JSON Web Token) 深入解析

JWT 是一种紧凑的、URL 安全的 Token 格式,用于在各方之间安全地传输信息。

3.3.1 结构 (Header, Payload, Signature)

JWT 由三部分组成,用点 . 分隔:

Header.Payload.Signature
  • Header (头部):
    • 通常包含 Token 类型 ("typ": "JWT") 和使用的签名算法 ("alg": "HS256""RS256" 等)。
    • Base64Url 编码。
    • 示例: {"alg": "HS256", "typ": "JWT"}
  • Payload (负载): 包含声明 (Claims)。声明是关于实体(通常是用户)和附加数据的语句。有三种类型的声明:
    • Registered Claims: 预定义的、建议使用的声明。如 iss (签发者), exp (过期时间), sub (主题/用户 ID), aud (受众)。
    • Public Claims: 可以自定义,但为了避免冲突应在 IANA JSON Web Token Registry 中定义,或者使用有抗冲突命名空间(如包含域名)的名称。
    • Private Claims: 自定义声明,用于在同意使用它们的各方之间共享信息。
    • Base64Url 编码。
    • 示例: {"sub": "1234567890", "name": "John Doe", "iat": 1516239022, "exp": 1516239022 + 3600}
  • Signature (签名): 用于验证消息在传输过程中未被篡改,并且对于使用私钥签名的 Token,还可以验证 JWT 的发送方是否真实。
    • 签名计算公式:Signature = SigningAlgorithm(Base64UrlEncode(Header) + "." + Base64UrlEncode(Payload), Secret/PrivateKey)
    • 例如,对于 HS256 (HMAC SHA-256):HMAC_SHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
    • 最终 Token:base64UrlEncode(Header) + "." + base64UrlEncode(Payload) + "." + base64UrlEncode(Signature)
3.3.2 签名算法与安全性
  • 对称签名 (如 HS256): 使用同一个密钥 (secret) 进行签名和验证。速度快,但密钥必须安全地在签发方和验证方共享。密钥泄露意味着任何人都可以签发有效 Token。适用于内部系统或单点验证。
  • 非对称签名 (如 RS256): 使用私钥 (private key) 签名,公钥 (public key) 验证。私钥由 Token 签发方严格保管,公钥可以分发给任何需要验证 Token 的方。安全性更高,是跨系统、跨组织的首选。速度比对称签名慢。
  • 无签名: "alg": "none"极其危险,不应在生产环境中使用。 任何人都可以篡改 Payload 并声称是有效的无签名 JWT。
3.3.3 优点与适用场景
  • 优点:
    • 无状态、可扩展性好。
    • 信息自包含,减少数据库查询。
    • 跨语言、跨平台支持好。
    • 可用于认证 (id_token) 和授权 (access_token)。
  • 适用场景:
    • RESTful API / 微服务认证授权。
    • 单点登录 (SSO)。
    • 移动应用认证。
    • 服务间安全通信。
3.3.4 安全注意事项
  • 敏感信息: 不要将高度敏感信息(如密码)放入 Payload。Payload 是 Base64 编码,不是加密!任何人都可以解码查看内容。JWT 保证的是内容未被篡改(签名),而不是内容保密。如需保密,应对整个 JWT 进行加密 (JWE - JSON Web Encryption)。
  • 密钥管理: 安全地存储密钥(对称)或私钥(非对称)。定期轮换密钥。
  • Token 有效期: 设置合理的过期时间 (exp claim)。使用 Refresh Token 机制获取新的 Access Token。
  • Token 存储: 客户端安全地存储 Token (如 HttpOnly Cookie, Secure Storage)。防止 XSS 攻击窃取 Token。
  • 令牌撤销: JWT 在过期前无法被服务器主动撤销。如果需要即时撤销能力,可能需要结合其他机制(如较短的过期时间、Token 黑名单、或使用 Opaque Token)。
  • 算法选择: 避免使用弱算法 (none, HS256 如果密钥强度不足)。优先使用 RS256, ES256 等非对称算法。
  • 验证所有字段: 验证时务必检查签名、iss (签发者)、aud (受众)、exp (过期时间)、nbf (生效时间) 等关键声明。

3.4 实战:使用 java-jwt 库创建和验证 JWT

我们将使用 com.auth0:java-jwt 库进行演示。

步骤 1:添加依赖


    com.auth0
    java-jwt
    4.4.0 

步骤 2:创建 JWT (签发)

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import java.util.Date;

public class JwtCreateExample {

    public static void main(String[] args) {
        // 1. 定义密钥 (HS256 对称算法示例,生产环境请使用强密钥并安全存储!)
        String secret = "mySuperSecretKey"; // 实际应用中应使用长且复杂的密钥,并从安全配置读取
        Algorithm algorithm = Algorithm.HMAC256(secret);

        // 2. 计算过期时间 (例如 1 小时后)
        long expiresAtMillis = System.currentTimeMillis() + (60 * 60 * 1000); // 1 hour
        Date expiresAt = new Date(expiresAtMillis);

        // 3. 创建 JWT Builder 并设置声明
        String token = JWT.create()
                .withIssuer("your-issuer") // iss - 签发者
                .withSubject("user123")    // sub - 主题 (通常是用户ID)
                .withAudience("your-audience") // aud - 受众 (接收Token的系统)
                .withExpiresAt(expiresAt)      // exp - 过期时间
                .withIssuedAt(new Date())      // iat - 签发时间
                .withClaim("name", "John Doe") // 自定义声明
                .withClaim("role", "admin")    // 自定义声明
                .sign(algorithm);              // 使用算法签名

        System.out.println("Generated JWT:");
        System.out.println(token);
    }
}

运行结果: 输出一个类似 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyMTIzIiwibmFtZSI6IkpvaG4gRG9lIiwicm9sZSI6ImFkbWluIiwiaXNzIjoieW91ci1pc3N1ZXIiLCJhdWQiOiJ5b3VyLWF1ZGllbmNlIiwiZXhwIjoxN... 的字符串。

步骤 3:验证 JWT (验证)

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;

public class JwtVerifyExample {

    public static void main(String[] args) {
        String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."; // 替换为上一步生成的Token

        String secret = "mySuperSecretKey"; // 必须与创建时使用的密钥一致
        Algorithm algorithm = Algorithm.HMAC256(secret);

        try {
            // 1. 创建 Verifier 实例,指定算法、签发者、受众
            JWTVerifier verifier = JWT.require(algorithm)
                    .withIssuer("your-issuer") // 必须匹配
                    .withAudience("your-audience") // 必须匹配
                    .build();

            // 2. 验证 Token
            DecodedJWT decodedJWT = verifier.verify(token);

            // 3. 如果验证通过,提取信息
            System.out.println("Token is valid!");
            System.out.println("Subject (User ID): " + decodedJWT.getSubject());
            System.out.println("Name: " + decodedJWT.getClaim("name").asString());
            System.out.println("Role: " + decodedJWT.getClaim("role").asString());
            System.out.println("Expires at: " + decodedJWT.getExpiresAt());

        } catch (JWTVerificationException exception) {
            // 验证失败 (签名无效、过期、iss/aud不匹配等)
            System.err.println("Token verification failed: " + exception.getMessage());
        }
    }
}

运行结果: 如果 Token 有效且匹配 issueraudience,将输出 Token 中包含的用户信息。如果无效(如修改 Token 字符串、过期、密钥错误),将捕获 JWTVerificationException 并打印错误信息。


4. API 访问控制:OAuth 2.0 中的 Token

OAuth 2.0 是一个授权框架,允许第三方应用在用户授权后,代表用户访问用户在另一个服务上的资源,而无需分享用户的密码。

4.1 OAuth 2.0 框架简介

主要角色:

  • 资源所有者 (Resource Owner): 通常是用户,拥有被访问资源的所有权。
  • 客户端 (Client): 想要访问用户资源的第三方应用 (如 Web App, Mobile App)。
  • 资源服务器 (Resource Server): 托管受保护资源的服务器 (如 API 服务器)。
  • 授权服务器 (Authorization Server): 在认证用户并获得授权后,向客户端颁发 Token 的服务器。

授权流程 (以授权码流程为例):

  1. 客户端引导用户到授权服务器登录并授权。
  2. 用户同意授权。
  3. 授权服务器将授权码 (authorization_code) 返回给客户端 (通常通过重定向)。
  4. 客户端使用授权码 + 客户端凭证向授权服务器请求 Access Token。
  5. 授权服务器验证授权码和客户端凭证,颁发 Access Token (和可选的 Refresh Token)。
  6. 客户端使用 Access Token 向资源服务器请求资源。
  7. 资源服务器验证 Access Token,返回受保护资源。

4.2 Access Token 与 Refresh Token

4.2.1 作用与生命周期
  • Access Token:
    • 作用: 客户端使用它访问受保护资源。它代表用户授予客户端的权限范围和有效期。
    • 生命周期: 短寿命 (几分钟到几小时)。一旦过期或泄露,危害时间有限。
    • 格式: 可以是 JWT (包含信息) 或 Opaque Token (只是一个随机字符串,验证需回查授权服务器)。
  • Refresh Token:
    • 作用: 当 Access Token 过期时,客户端可以使用 Refresh Token 向授权服务器请求一个新的 Access Token (可能同时得到新的 Refresh Token)。它代表了用户授予客户端的长期授权。
    • 生命周期: 长寿命 (几天、几周、几个月,甚至更长,但应可撤销)。它比 Access Token 更敏感!
    • 格式: 通常是 Opaque Token。
    • 存储: 必须由客户端安全存储 (如服务器端 Web App 的数据库、移动设备的 Secure Enclave)。绝不能暴露给浏览器 JavaScript (防止 XSS 窃取)。
4.2.2 最佳安全实践
  • Access Token:
    • 使用 HTTPS 传输。
    • 设置短有效期。
    • 避免存储敏感信息 (如果使用 JWT)。
    • 客户端安全存储 (如移动端 Secure Storage, Web 应用 Session Storage 或内存)。
  • Refresh Token:
    • 使用 HTTPS 传输。
    • 绑定到特定的客户端和用户 (防止被盗后在其他地方使用)。
    • 提供撤销机制。
    • 仅在安全的后端通道交换 (避免暴露给前端)。
    • 客户端必须极其安全地存储。
    • 轮换策略:每次使用 Refresh Token 获取新 Access Token 时,授权服务器可以颁发一个新的 Refresh Token 并使旧的失效。

4.3 实战:模拟 OAuth 2.0 授权服务器颁发 Token (简化版)

这是一个极度简化的模拟,仅用于演示核心概念。真实系统涉及数据库、用户认证、授权码存储、HTTPS 等。

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class MockAuthorizationServer {

    private static final Map authorizationCodeStore = new HashMap<>(); // 模拟存储授权码和用户ID的映射
    private static final Map refreshTokenStore = new HashMap<>(); // 模拟存储Refresh Token和用户ID的映射
    private static final String SECRET = "authServerSecret"; // 授权服务器密钥 (用于签名JWT)

    // 步骤1:用户认证后生成授权码 (模拟)
    public static String generateAuthorizationCode(String userId) {
        String authCode = UUID.randomUUID().toString(); // 生成随机授权码
        authorizationCodeStore.put(authCode, userId); // 存储授权码关联的用户ID
        return authCode;
    }

    // 步骤2:客户端用授权码换取Token (模拟/token 端点)
    public static Map exchangeCodeForTokens(String authCode, String clientId, String clientSecret) {
        // 1. 验证授权码 (简化:检查是否存在)
        String userId = authorizationCodeStore.get(authCode);
        if (userId == null) {
            throw new RuntimeException("Invalid authorization code");
        }
        // 2. (简化) 这里应验证 clientId 和 clientSecret
        authorizationCodeStore.remove(authCode); // 授权码一次性使用,移除

        // 3. 生成 Access Token (JWT)
        Algorithm algorithm = Algorithm.HMAC256(SECRET);
        long accessExpiresAt = System.currentTimeMillis() + (10 * 60 * 1000); // 10分钟过期
        String accessToken = JWT.create()
                .withSubject(userId)
                .withIssuer("MockAuthServer")
                .withExpiresAt(new Date(accessExpiresAt))
                .withClaim("scope", "read write") // 模拟权限范围
                .sign(algorithm);

        // 4. 生成 Refresh Token (随机字符串)
        String refreshToken = UUID.randomUUID().toString();
        refreshTokenStore.put(refreshToken, userId); // 存储Refresh Token关联的用户ID

        // 5. 返回 Token
        Map tokens = new HashMap<>();
        tokens.put("access_token", accessToken);
        tokens.put("token_type", "Bearer");
        tokens.put("expires_in", "600"); // 10分钟(600秒)
        tokens.put("refresh_token", refreshToken);
        return tokens;
    }

    // 步骤3:使用Refresh Token获取新Access Token (模拟/token 端点)
    public static Map refreshAccessToken(String refreshToken) {
        // 1. 验证Refresh Token
        String userId = refreshTokenStore.get(refreshToken);
        if (userId == null) {
            throw new RuntimeException("Invalid refresh token");
        }

        // 2. 生成新的 Access Token
        Algorithm algorithm = Algorithm.HMAC256(SECRET);
        long accessExpiresAt = System.currentTimeMillis() + (10 * 60 * 1000); // 新Token有效期10分钟
        String newAccessToken = JWT.create()
                .withSubject(userId)
                .withIssuer("MockAuthServer")
                .withExpiresAt(new Date(accessExpiresAt))
                .withClaim("scope", "read write")
                .sign(algorithm);

        // 3. (可选) 可以返回新的Refresh Token并使旧的失效 (此处简化,返回旧的Refresh Token)
        Map tokens = new HashMap<>();
        tokens.put("access_token", newAccessToken);
        tokens.put("token_type", "Bearer");
        tokens.put("expires_in", "600");
        tokens.put("refresh_token", refreshToken); // 返回同一个Refresh Token
        return tokens;
    }

    public static void main(String[] args) {
        // 模拟流程
        String userId = "user123";
        // 1. 用户登录授权后,生成授权码
        String authCode = generateAuthorizationCode(userId);
        System.out.println("Generated Auth Code: " + authCode);

        // 2. 客户端用授权码换取Token
        Map tokens = exchangeCodeForTokens(authCode, "clientId", "clientSecret");
        System.out.println("Access Token: " + tokens.get("access_token"));
        System.out.println("Refresh Token: " + tokens.get("refresh_token"));

        // 3. 模拟 Access Token 过期后,用 Refresh Token 获取新的
        Map newTokens = refreshAccessToken(tokens.get("refresh_token"));
        System.out.println("New Access Token: " + newTokens.get("access_token"));
    }
}

运行结果: 模拟生成授权码、换取 Access Token 和 Refresh Token、以及使用 Refresh Token 刷新 Access Token 的过程。

4.4 实战:资源服务器验证 Access Token (简化版)

资源服务器收到携带 Access Token 的请求后,需要验证其有效性。

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;

public class MockResourceServer {

    private static final String AUTH_SERVER_SECRET = "authServerSecret"; // 必须与授权服务器一致

    public static boolean verifyAccessToken(String accessToken) {
        try {
            Algorithm algorithm = Algorithm.HMAC256(AUTH_SERVER_SECRET);
            JWTVerifier verifier = JWT.require(algorithm)
                    .withIssuer("MockAuthServer") // 验证签发者
                    .build();
            DecodedJWT decodedJWT = verifier.verify(accessToken);
            // 如果验证通过,可以进一步检查 scope 等声明是否符合请求的资源
            System.out.println("Token verified for user: " + decodedJWT.getSubject());
            return true;
        } catch (JWTVerificationException exception) {
            System.err.println("Token verification failed: " + exception.getMessage());
            return false;
        }
    }

    public static void main(String[] args) {
        // 假设这是从请求头 Authorization: Bearer  中提取的Token
        String accessToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."; // 替换为有效的Access Token字符串

        if (verifyAccessToken(accessToken)) {
            System.out.println("Access granted to protected resource!");
            // 这里处理受保护的资源逻辑
        } else {
            System.out.println("Access denied!");
        }
    }
}

运行结果: 验证 Token 的有效性,并根据结果模拟是否允许访问受保护资源。


5. 令牌化 (Tokenization) 与敏感数据处理

令牌化 (Tokenization) 是一种数据安全技术,用于保护敏感信息。它用 Token 替代原始敏感数据。Token 本身没有内在价值或意义,无法被反向推导出原始数据。

5.1 令牌化概念 (非认证 Token)

  • 核心思想: 将敏感数据 (如信用卡号 4111 1111 1111 1111) 发送给一个安全的 令牌化系统
  • 令牌化系统:
    • 安全地存储原始数据 (通常在一个高度安全的数据库或硬件安全模块 HSM 中)。
    • 生成一个随机的、唯一的 Token (如 tok_7a8b9c0d1e2f3g4h)。
    • 将这个 Token 返回给请求方。
  • 应用程序: 存储和使用这个 Token (tok_7a8b9c0d1e2f3g4h) 代替原始信用卡号进行后续处理(如交易请求、存储订单信息)。
  • 需要原始数据时: 只有授权系统可以向令牌化系统提交 Token 来取回原始数据。

5.2 应用场景:支付卡信息 (PCI DSS)、个人身份信息 (PII) 保护

  • PCI DSS 合规: 支付卡行业数据安全标准要求保护持卡人数据。使用令牌化可以显著减少需要符合 PCI DSS 要求的系统范围,因为只有令牌化系统存储原始卡号。
  • 保护 PII: 如身份证号、护照号、社保号、健康信息等。应用系统存储 Token 而非原始数据,降低数据泄露风险。
  • 测试数据脱敏: 为开发测试环境提供符合生产数据的 Token 化版本,保护生产数据隐私。

5.3 与加密的区别

  • 加密:
    • 使用密钥和算法将原始数据转换为密文。
    • 密文可以通过密钥解密回原始数据。
    • 加密密钥的安全管理是关键。
    • 加密后的数据长度通常与原始数据相关。
  • 令牌化:
    • 用随机生成的 Token 替换原始数据。
    • Token 本身没有意义,也无法通过 Token 本身推导出原始数据(除非访问令牌化系统)。
    • 原始数据安全地存储在令牌化系统中。
    • Token 的格式和长度可以自定义(如保留最后4位卡号 tok_xxxx1111),与原始数据无关。
    • 优势: 即使 Token 数据库被泄露,攻击者也无法获得原始敏感数据(只要令牌化系统的核心数据存储未被攻破)。密钥管理负担主要在令牌化系统。

5.4 实战:简易支付卡令牌化系统示例

这是一个高度简化的内存实现,用于演示概念。真实系统需要持久化存储、HSM、高可用、严格访问控制等。

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class SimpleTokenizationSystem {

    // 模拟安全存储:Token -> 原始卡号
    private static final Map tokenVault = new HashMap<>();
    // 模拟反向查找:原始卡号 -> Token (简化,实际可能需要加盐哈希存储卡号)
    private static final Map cardToTokenMap = new HashMap<>();

    // 令牌化:传入卡号,返回Token
    public static String tokenize(String cardNumber) {
        // 检查是否已存在Token (去重)
        if (cardToTokenMap.containsKey(cardNumber)) {
            return cardToTokenMap.get(cardNumber);
        }

        // 生成唯一Token
        String token = "tok_" + UUID.randomUUID().toString().replace("-", "");
        // 安全存储映射关系 (模拟)
        tokenVault.put(token, cardNumber);
        cardToTokenMap.put(cardNumber, token);

        return token;
    }

    // 去令牌化:传入Token,返回原始卡号 (需要权限)
    public static String detokenize(String token) {
        // 验证Token是否存在
        if (!tokenVault.containsKey(token)) {
            throw new RuntimeException("Invalid token");
        }
        // 返回原始卡号 (模拟权限检查通过)
        return tokenVault.get(token);
    }

    // 模拟应用使用Token
    public static void main(String[] args) {
        String sensitiveCardNumber = "4111111111111111";

        // 1. 令牌化:应用将卡号发送给令牌化系统,得到Token
        String token = tokenize(sensitiveCardNumber);
        System.out.println("Original Card: " + sensitiveCardNumber);
        System.out.println("Token: " + token);

        // 2. 应用存储和使用Token (例如存储在订单表中)
        System.out.println("Application stores and uses token: " + token);

        // 3. 后续需要处理支付时(有权限),应用将Token发送给令牌化系统获取原始卡号
        try {
            String retrievedCardNumber = detokenize(token);
            System.out.println("Detokenized Card (for processing): " + retrievedCardNumber);
            System.out.println("Match Original? " + sensitiveCardNumber.equals(retrievedCardNumber));
        } catch (Exception e) {
            System.err.println("Error detokenizing: " + e.getMessage());
        }
    }
}

运行结果:

Original Card: 4111111111111111
Token: tok_6b29fc456c1b46e0a528f0c8e6f6c7d1
Application stores and uses token: tok_6b29fc456c1b46e0a528f0c8e6f6c7d1
Detokenized Card (for processing): 4111111111111111
Match Original? true

这个示例展示了令牌化的基本流程:敏感数据被 Token 替换存储,仅在需要时由授权系统还原。


6. 系统案例:综合应用

6.1 案例一:Java 源码关键词提取工具

目标: 读取一个 Java 源文件,提取出所有关键字 Token,并统计每个关键字出现的次数。 技术点: 文件读取、词法分析 (使用 PatternMatcher 识别关键字)。

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class JavaKeywordExtractor {

    // Java 关键字列表 (根据Java版本可能略有不同)
    private static final Set JAVA_KEYWORDS = Set.of(
            "abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class", "const",
            "continue", "default", "do", "double", "else", "enum", "extends", "final", "finally", "float",
            "for", "goto", "if", "implements", "import", "instanceof", "int", "interface", "long", "native",
            "new", "package", "private", "protected", "public", "return", "short", "static", "strictfp", "super",
            "switch", "synchronized", "this", "throw", "throws", "transient", "try", "void", "volatile", "while"
    );

    public static void main(String[] args) {
        if (args.length != 1) {
            System.err.println("Usage: JavaKeywordExtractor ");
            System.exit(1);
        }
        String filePath = args[0];

        try {
            // 读取Java文件内容
            String javaSource = Files.readString(Paths.get(filePath));

            // 使用正则匹配单词边界 () 来标识可能的标识符/关键字
            Pattern wordPattern = Pattern.compile("w+");
            Matcher matcher = wordPattern.matcher(javaSource);

            // 统计关键字出现次数
            Map keywordCount = new HashMap<>();

            while (matcher.find()) {
                String word = matcher.group();
                // 检查是否是关键字
                if (JAVA_KEYWORDS.contains(word)) {
                    keywordCount.put(word, keywordCount.getOrDefault(word, 0) + 1);
                }
            }

            // 输出结果
            System.out.println("Keyword occurrences in '" + filePath + "':");
            keywordCount.entrySet().stream()
                    .sorted(Map.Entry.comparingByKey()) // 按关键字字母排序
                    .forEach(entry -> System.out.printf("%-15s: %d%n", entry.getKey(), entry.getValue()));

        } catch (IOException e) {
            System.err.println("Error reading file: " + e.getMessage());
        }
    }
}

使用方法: 编译后,在命令行运行 java JavaKeywordExtractor path/to/YourJavaFile.java输出: 列出该 Java 文件中出现的所有关键字及其出现次数。

6.2 案例二:基于 JWT 的 RESTful API 用户认证系统

目标: 实现一个简单的 Spring Boot RESTful API,使用 JWT 进行用户登录认证和后续请求的授权。 技术点: Spring Boot, Spring Security, JWT (java-jwt), 用户存储 (简化内存)。

步骤 1:项目结构 (Maven) & 依赖 (pom.xml)


    
        org.springframework.boot
        spring-boot-starter-web
    
    
        org.springframework.boot
        spring-boot-starter-security
    
    
        com.auth0
        java-jwt
        4.4.0
    

步骤 2:用户模型与内存存储 (UserUserRepository)

// User.java
public class User {
    private String username;
    private String password; // 注意:真实应用应存储哈希加盐后的密码!
    private String role;

    // Constructor, Getters, Setters
    public User(String username, String password, String role) {
        this.username = username;
        this.password = password;
        this.role = role;
    }
    // ... getters and setters ...
}

// UserRepository.java (内存存储)
import org.springframework.stereotype.Repository;
import java.util.HashMap;
import java.util.Map;

@Repository
public class UserRepository {
    private final Map users = new HashMap<>();

    public UserRepository() {
        // 初始化用户 (密码明文存储仅用于演示!生产环境必须哈希加盐)
        users.put("user", new User("user", "password", "USER"));
        users.put("admin", new User("admin", "adminpass", "ADMIN"));
    }

    public User findByUsername(String username) {
        return users.get(username);
    }
}

步骤 3:JWT 工具类 (JwtUtil)

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.JWTVerifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.Date;

@Component
public class JwtUtil {

    @Value("${jwt.secret}") // 从application.properties读取
    private String secret;

    @Value("${jwt.expiration}") // 过期时间(毫秒)
    private long expiration;

    public String generateToken(String username, String role) {
        Algorithm algorithm = Algorithm.HMAC256(secret);
        return JWT.create()
                .withSubject(username)
                .withClaim("role", role)
                .withIssuedAt(new Date())
                .withExpiresAt(new Date(System.currentTimeMillis() + expiration))
                .sign(algorithm);
    }

    public DecodedJWT verifyToken(String token) {
        Algorithm algorithm = Algorithm.HMAC256(secret);
        JWTVerifier verifier = JWT.require(algorithm).build();
        return verifier.verify(token); // 如果无效会抛出异常
    }

    public String getUsernameFromToken(DecodedJWT jwt) {
        return jwt.getSubject();
    }

    public String getRoleFromToken(DecodedJWT jwt) {
        return jwt.getClaim("role").asString();
    }
}

步骤 4:登录认证 (AuthControllerAuthenticationRequest)

// AuthenticationRequest.java
public class AuthenticationRequest {
    private String username;
    private String password;
    // Getters, Setters
}

// AuthController.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class AuthController {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private JwtUtil jwtUtil;

    @Autowired
    private UserRepository userRepository; // 简化,实际应用应使用 UserDetailsService

    @PostMapping("/login")
    public ResponseEntity login(@RequestBody AuthenticationRequest request) {
        try {
            // 1. 使用Spring Security进行认证
            Authentication authentication = authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword())
            );
            // 2. 认证成功后,加载用户详情 (这里简化,直接查询)
            User user = userRepository.findByUsername(request.getUsername());
            if (user == null) {
                throw new RuntimeException("User not found");
            }
            // 3. 生成JWT Token
            String token = jwtUtil.generateToken(user.getUsername(), user.getRole());
            // 4. 返回Token
            return ResponseEntity.ok(Map.of("token", token));
        } catch (Exception e) {
            return ResponseEntity.status(401).body("Authentication failed: " + e.getMessage());
        }
    }
}

步骤 5:配置 Spring Security (SecurityConfig)

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserRepository userRepository; // 简化,实际应使用 UserDetailsService

    @Autowired
    private JwtUtil jwtUtil;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 内存用户配置 (简化,生产环境用数据库)
        auth.inMemoryAuthentication()
                .withUser("user").password("{noop}password").roles("USER") // {noop}表示明文(仅演示)
                .and()
                .withUser("admin").password("{noop}adminpass").roles("ADMIN");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 无状态,用Token
                .and()
                .authorizeRequests()
                .antMatchers("/login").permitAll() // 登录端点开放
                .antMatchers("/admin/**").hasRole("ADMIN") // /admin 需要ADMIN角色
                .antMatchers("/user/**").hasAnyRole("USER", "ADMIN") // /user 需要USER或ADMIN
                .anyRequest().authenticated() // 其他请求需要认证
                .and()
                .addFilterBefore(new JwtTokenFilter(jwtUtil), UsernamePasswordAuthenticationFilter.class); // JWT过滤器
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean(); // 暴露AuthenticationManager Bean
    }

    // 简化PasswordEncoder (仅演示,生产环境必须用BCrypt等)
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new PasswordEncoder() {
            @Override
            public String encode(CharSequence rawPassword) {
                return rawPassword.toString(); // 明文存储,危险!
            }
            @Override
            public boolean matches(CharSequence rawPassword, String encodedPassword) {
                return rawPassword.toString().equals(encodedPassword);
            }
        };
    }
}

步骤 6:JWT 请求过滤器 (JwtTokenFilter)

import com.auth0.jwt.exceptions.JWTVerificationException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class JwtTokenFilter extends OncePerRequestFilter {

    private final JwtUtil jwtUtil;

    public JwtTokenFilter(JwtUtil jwtUtil) {
        this.jwtUtil = jwtUtil;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        // 1. 从请求头获取Token
        String authorizationHeader = request.getHeader("Authorization");
        if (authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")) {
            filterChain.doFilter(request, response); // 没有Token,继续过滤链 (可能被后续拦截)
            return;
        }
        String token = authorizationHeader.substring(7); // 去掉 "Bearer "

        try {
            // 2. 验证Token
            DecodedJWT decodedJWT = jwtUtil.verifyToken(token);
            String username = jwtUtil.getUsernameFromToken(decodedJWT);
            String role = jwtUtil.getRoleFromToken(decodedJWT);

            // 3. 创建Authentication对象 (简化,实际应从数据库加载用户权限)
            // 这里假设用户存在且有效
            UserDetails userDetails = org.springframework.security.core.userdetails.User.builder()
                    .username(username)
                    .password("") // 密码在Token中已不再需要
                    .roles(role)
                    .build();

            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
                    userDetails, null, userDetails.getAuthorities());

            // 4. 设置认证信息到SecurityContext
            SecurityContextHolder.getContext().setAuthentication(authentication);

        } catch (JWTVerificationException e) {
            // Token无效,清除上下文
            SecurityContextHolder.clearContext();
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid JWT Token");
            return;
        }

        filterChain.doFilter(request, response);
    }
}

步骤 7:受保护资源端点 (UserController, AdminController)

// UserController.java
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/user")
public class UserController {

    @GetMapping("/hello")
    public String userHello() {
        return "Hello, User!";
    }
}

// AdminController.java
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/admin")
public class AdminController {

    @GetMapping("/hello")
    public String adminHello() {
        return "Hello, Admin!";
    }
}

步骤 8:application.properties

jwt.secret=mySuperSecretKeyForJWT123! # 强密钥
jwt.expiration=3600000 # 1小时 (毫秒)
server.port=8080

测试流程:

  1. 登录: POST http://localhost:8080/login with Body {"username": "user", "password": "password"}
    • Response: {"token": "eyJhbGciOiJIUzI1NiIs..."}
  2. 访问 User 资源: GET http://localhost:8080/user/hello with Header Authorization: Bearer
    • Response: "Hello, User!"
  3. 访问 Admin 资源 (用 user Token): GET http://localhost:8080/admin/hello with Header Authorization: Bearer
    • Response: 403 Forbidden (因为 user 角色无权访问 admin 端点)
  4. 用 admin 用户登录: POST http://localhost:8080/login with Body {"username": "admin", "password": "adminpass"}
  5. 访问 Admin 资源 (用 admin Token): GET http://localhost:8080/admin/hello with Header Authorization: Bearer
    • Response: "Hello, Admin!"

6.3 案例三:简易 OAuth 2.0 受保护的资源访问系统

目标: 模拟一个简化的 OAuth 2.0 流程,包含资源所有者、客户端、授权服务器和资源服务器。使用前面 MockAuthorizationServerMockResourceServer 的逻辑进行整合。 说明: 这是一个控制台模拟程序,将步骤打印出来。真实应用需要网络通信、UI 等。

public class OAuth2Simulation {

    public static void main(String[] args) {
        // 角色初始化
        String resourceOwner = "user123"; // 资源所有者
        String clientId = "myClientApp";
        String clientSecret = "clientSecret123";
        String protectedResource = "user_profile_data";

        // 1. 资源所有者操作:在客户端发起请求,客户端引导到授权服务器
        System.out.println("Step 1: Client redirects Resource Owner to Authorization Server for login and consent.");

        // 2. 授权服务器操作:认证用户,获得授权,生成授权码
        System.out.println("Step 2: Resource Owner logs in and grants permission on Authorization Server.");
        String authCode = MockAuthorizationServer.generateAuthorizationCode(resourceOwner);
        System.out.println("Authorization Server generates Auth Code: " + authCode + " and redirects back to Client.");

        // 3. 客户端操作:使用授权码向授权服务器请求 Token
        System.out.println("Step 3: Client exchanges Auth Code for Access Token and Refresh Token.");
        Map tokens = MockAuthorizationServer.exchangeCodeForTokens(authCode, clientId, clientSecret);
        String accessToken = tokens.get("access_token");
        String refreshToken = tokens.get("refresh_token");
        System.out.println("Client receives Access Token: " + accessToken);
        System.out.println("Client receives Refresh Token: " + refreshToken);

        // 4. 客户端操作:使用 Access Token 访问资源服务器
        System.out.println("Step 4: Client accesses Protected Resource on Resource Server with Access Token.");
        boolean accessGranted = MockResourceServer.verifyAccessToken(accessToken);
        if (accessGranted) {
            System.out.println("Resource Server grants access. Resource: " + protectedResource + " is provided.");
        } else {
            System.out.println("Resource Server denies access.");
        }

        // 5. 模拟 Access Token 过期
        System.out.println("
--- Simulating Access Token Expiration ---");

        // 6. 客户端操作:使用 Refresh Token 获取新的 Access Token
        System.out.println("Step 6: Client uses Refresh Token to get new Access Token.");
        Map newTokens = MockAuthorizationServer.refreshAccessToken(refreshToken);
        String newAccessToken = newTokens.get("access_token");
        System.out.println("Client receives new Access Token: " + newAccessToken);

        // 7. 客户端操作:使用新的 Access Token 再次访问资源服务器
        System.out.println("Step 7: Client accesses Protected Resource again with new Access Token.");
        accessGranted = MockResourceServer.verifyAccessToken(newAccessToken);
        if (accessGranted) {
            System.out.println("Resource Server grants access. Resource: " + protectedResource + " is provided.");
        } else {
            System.out.println("Resource Server denies access.");
        }
    }
}

运行结果: 在控制台输出模拟的 OAuth 2.0 授权码流程步骤,包括授权码获取、Token 交换、资源访问、Token 刷新和再次访问。


这份指南涵盖了 Java Token 的多个关键方面,从编译器基础的词法 Token 到安全领域的认证授权 Token (JWT, OAuth),再到数据保护的令牌化。每个部分都包含通俗的解释、原理分析和可直接运行的实战代码示例。最后的系统案例展示了 Token 技术的综合应用。希望这份全面的指南能帮助你深入理解和应用 Java Token 技术。

本文地址:https://www.yitenyun.com/5627.html

搜索文章

Tags

#服务器 #python #pip #conda #人工智能 #微信 #ios面试 #ios弱网 #断点续传 #ios开发 #objective-c #ios #ios缓存 #远程工作 #Trae #IDE #AI 原生集成开发环境 #Trae AI 香港站群服务器 多IP服务器 香港站群 站群服务器 #kubernetes #笔记 #平面 #容器 #linux #学习方法 #运维 #log4j #ollama #飞牛nas #fnos #科技 #深度学习 #自然语言处理 #神经网络 #kylin #docker #arm #hadoop #hbase #hive #zookeeper #spark #kafka #flink #银河麒麟高级服务器操作系统安装 #银河麒麟高级服务器V11配置 #设置基础软件仓库时出错 #银河麒高级服务器系统的实操教程 #生产级部署银河麒麟服务系统教程 #Linux系统的快速上手教程 #低代码 #爬虫 #音视频 #AI编程 #飞书 #学习 #语言模型 #大模型 #ai #ai大模型 #agent #华为云 #部署上线 #动静分离 #Nginx #新人首发 #大数据 #职场和发展 #程序员创富 #ARM服务器 # GLM-4.6V # 多模态推理 #fastapi #html #css #PyTorch #模型训练 #星图GPU #分阶段策略 #模型协议 #ssh #ide #java #开发语言 #前端 #javascript #架构 #经验分享 #安卓 #MobaXterm #ubuntu #langchain #数据库 #harmonyos #鸿蒙PC #C++ #Reactor #物联网 #websocket #windows #nginx #开源 #进程控制 #自动化 #ansible #云计算 #驱动开发 #c++ #github #git #node.js #unity #c# #游戏引擎 #私有化部署 #pytorch #aws #tcp/ip #网络 #qt #区块链 #测试用例 #生活 #word #umeditor粘贴word #ueditor粘贴word #ueditor复制word #ueditor上传word图片 #gemini #gemini国内访问 #gemini api #gemini中转搭建 #Cloudflare #cpolar #openHiTLS #TLCP #DTLCP #密码学 #商用密码算法 #fabric #postgresql #android #腾讯云 #Conda # 私有索引 # 包管理 #大模型学习 #AI大模型 #大模型教程 #大模型入门 #jar #数信院生信服务器 #Rstudio #生信入门 #生信云服务器 #vue上传解决方案 #vue断点续传 #vue分片上传下载 #vue分块上传下载 #sql #AIGC #agi #风控模型 #决策盲区 #内网穿透 #mysql #算法 #牛客周赛 #云原生 #iventoy #VmWare #OpenEuler #RTP over RTSP #RTP over TCP #RTSP服务器 #RTP #TCP发送RTP #dify #ci/cd #jenkins #gitlab #pycharm #Ansible # 自动化部署 # VibeThinker #Harbor #vscode #文心一言 #AI智能体 #矩阵 #线性代数 #AI运算 #向量 #机器学习 #flutter #centos #svn #后端 #缓存 #硬件工程 #mobaxterm #计算机视觉 #http #项目 #高并发 #spring cloud #spring #vue.js #json #serverless #diskinfo # TensorFlow # 磁盘健康 #microsoft #儿童书籍 #儿童诗歌 #童话故事 #经典好书 #儿童文学 #好书推荐 #经典文学作品 #鸿蒙 #边缘计算 #mcp #mcp server #AI实战 #阿里云 #重构 #ecmascript #elementui #开源软件 #FTP服务器 #流程图 #论文阅读 #信息可视化 #c语言 #FaceFusion # Token调度 # 显存优化 #数学建模 #设备驱动 #芯片资料 #网卡 #php #shell #CPU利用率 #2026年美赛C题代码 #2026年美赛 #java-ee #分布式 #华为 #iBMC #UltraISO #性能优化 #spring boot #java大文件上传 #java大文件秒传 #java大文件上传下载 #java文件传输解决方案 #springboot #超算服务器 #算力 #高性能计算 #仿真分析工作站 #prometheus #jmeter #功能测试 #软件测试 #自动化测试 #Ubuntu服务器 #硬盘扩容 #命令行操作 #VMware #stm32 #CFD #mcu #mongodb #数据结构 #MCP #MCP服务器 #企业开发 #ERP #项目实践 #.NET开发 #C#编程 #编程与数学 #内存治理 #django #多个客户端访问 #IO多路复用 #回显服务器 #TCP相关API #mvp #个人开发 #设计模式 #llama #opencv #进程 #web安全 #安全 #蓝桥杯 #正则 #正则表达式 #信息与通信 #PyCharm # 远程调试 # YOLOFuse #时序数据库 #程序人生 #科研 #博士 #产品经理 #ui #团队开发 #墨刀 #figma #Dell #PowerEdge620 #内存 #硬盘 #RAID5 #Windows 更新 #搜索引擎 #导航网 #游戏 #select #大语言模型 #长文本处理 #GLM-4 #Triton推理 #嵌入式 #毕业设计 #系统架构 #rocketmq #网络协议 #Linux #TCP #线程 #线程池 #uni-app #小程序 #notepad++ #es安装 #RAGFlow #DeepSeek-R1 #powerpoint #Com #redis #web #webdav #chatgpt #DeepSeek #AI #DS随心转 #鸭科夫 #逃离鸭科夫 #鸭科夫联机 #鸭科夫异地联机 #开服 #flask #FL Studio #FLStudio #FL Studio2025 #FL Studio2026 #FL Studio25 #FL Studio26 #水果软件 #vim #gcc #yum #lvs #负载均衡 #scrapy #课程设计 #jvm #SSH # ProxyJump # 跳板机 #哈希算法 #散列表 #dreamweaver #HCIA-Datacom #H12-811 #题库 #最新题库 #计算机网络 #线性回归 #服务器繁忙 #transformer #jetty #AI写作 #Android #Bluedroid #Agent #程序员 #ffmpeg #学习笔记 #jdk #udp #酒店客房管理系统 #毕设 #论文 #https #leetcode #wsl #L2C #勒让德到切比雪夫 #钉钉 #机器人 #LLM #3d #ssl #深度优先 #DFS #企业微信 #arm开发 #嵌入式硬件 #堡垒机 #安恒明御堡垒机 #windterm #自动驾驶 #能源 #todesk #servlet #阻塞队列 #生产者消费者模型 #服务器崩坏原因 #SSM 框架 #孕期健康 #产品服务推荐 #推荐系统 #用户交互 #PowerBI #企业 #golang #vllm #Streamlit #Qwen #本地部署 #AI聊天机器人 #数据集 #零售 #AI产品经理 #大模型开发 #京东云 #mmap #nio #语音识别 #rabbitmq #protobuf #我的世界 #游戏私服 #云服务器 #网络安全 #智能手机 #全能视频处理软件 #视频裁剪工具 #视频合并工具 #视频压缩工具 #视频字幕提取 #视频处理工具 #pjsip #YOLO #逻辑回归 #电脑 #everything #AB包 #信号处理 #目标跟踪 #Canal #Tracker 服务器 #响应最快 #torrent 下载 #2026年 #Aria2 可用 #迅雷可用 #BT工具通用 #社科数据 #数据分析 #数据挖掘 #数据统计 #经管数据 #单片机 #sqlserver #压枪 #claude #vue3 #天地图 #403 Forbidden #天地图403错误 #服务器403问题 #天地图API #部署报错 #autosar #数据仓库 #AI论文写作工具 #学术论文创作 #论文效率提升 #MBA论文写作 #操作系统 #cnn #DisM++ # 系统维护 #gitee #svm #amdgpu #kfd #ROCm #求职招聘 #面试 #蓝耘智算 #守护进程 #复用 #screen #数模美赛 #matlab #whisper #就业 #openclaw #分类 #abtest #iphone #聚类 #TURN # WebRTC # HiChatBox #电气工程 #C# #PLC #架构师 #软考 #系统架构师 #openresty #lua #OCR #文字检测 #AI大模型应用开发 #SSH Agent Forwarding # PyTorch # 容器化 #ESXi #贪心算法 #pdf #paddlepaddle #其他 #需求分析 #scala #测试工具 #压力测试 #新浪微博 #前端框架 #支持向量机 #启发式算法 #debian #oracle #adb #CISSP #CISSP考点 #信息安全 #CISSP哪里考 #公众号:厦门微思网络 #+微信号:xmweisi #排序算法 #插入排序 #Chat平台 #ARM架构 #1024程序员节 #考研 #软件工程 #HeyGem # 局域网访问 # 批量处理 #GB/T4857 #GB/T4857.17 #GB/T4857测试 #claude code #codex #code cli #ccusage #银河麒麟 #系统升级 #信创 #国产化 #ModelEngine #银河麒麟操作系统 #openssh #华为交换机 #信创终端 #Ascend #MindIE #OBC #金融 #金融投资Agent #gpu算力 #elasticsearch #版本控制 #Git入门 #开发工具 #代码托管 #twitter #ssm #ProCAST2025 #ProCast #脱模 #顶出 #应力计算 #铸造仿真 #变形计算 #n8n #laravel #里氏替换原则 #幼儿园 #园长 #幼教 #Keycloak #Quarkus #AI编程需求分析 #推荐算法 #sizeof和strlen区别 #sizeof #strlen #计算数据类型字节数 #计算字符串长度 #googlecloud #若依 #quartz #框架 #七年级上册数学 #有理数 #有理数的加法法则 #绝对值 #树莓派4b安装系统 #流量运营 #用户运营 #我的世界服务器搭建 #minecraft #生信 #react native #react.js #文生视频 #CogVideoX #AI部署 #智能路由器 #环境搭建 #pandas #matplotlib #tomcat #firefox #journalctl #rust #双指针 #流量监控 #selenium #RAG #全链路优化 #实战教程 #wordpress #雨云 #LobeChat #vLLM #GPU加速 #macos #数组 #fastmcp #MC #几何学 #拓扑学 #链表 #链表的销毁 #链表的排序 #链表倒置 #判断链表是否有环 #grafana #eBPF #长文本理解 #glm-4 #推理部署 #SSH反向隧道 # Miniconda # Jupyter远程访问 #homelab #Lattepanda #Jellyfin #Plex #Emby #Kodi #电商 #.net #python学习路线 #python基础 #python进阶 #python标准库 #web3 #gpu #nvcc #cuda #nvidia #数据结构与算法 #TensorRT # Triton # 推理优化 #asp.net大文件上传 #asp.net大文件上传下载 #asp.net大文件上传源码 #ASP.NET断点续传 #asp.net上传文件夹 #SSH别名 # CUDA #人脸识别 #人脸核身 #活体检测 #身份认证与人脸对比 #H5 #微信公众号 #ICPC #智慧校园解决方案 #智慧校园一体化平台 #智慧校园选型 #智慧校园采购 #智慧校园软件 #智慧校园专项资金 #智慧校园定制开发 #LangGraph #模型上下文协议 #MultiServerMCPC #load_mcp_tools #load_mcp_prompt #ping通服务器 #读不了内网数据库 #bug菌问答团队 #dubbo #测试流程 #金融项目实战 #P2P #建筑缺陷 #红外 #结构体 #ISP Pipeline #行缓冲 #webrtc # 公钥认证 #微信小程序 #漏洞 #数码相机 #epoll #高级IO #改行学it #创业创新 # 服务器IP访问 # 端口映射 #游戏美术 #技术美术 #游戏策划 #游戏程序 #用户体验 #无人机 #Deepoc #具身模型 #开发板 #未来 #论文笔记 #HBA卡 #RAID卡 #机器视觉 #6D位姿 #asp.net #Coze工作流 #AI Agent指挥官 #多智能体系统 #tdengine #制造 #涛思数据 #VS Code调试配置 #LoRA # RTX 3090 # lora-scripts #Proxmox VE #虚拟化 #硬件 #ddos #windbg分析蓝屏教程 #测试覆盖率 #单元测试 #可用性测试 #GPU服务器 #8U #硬件架构 #fiddler #rtmp #银河麒麟部署 #银河麒麟部署文档 #银河麒麟linux #银河麒麟linux部署教程 #串口服务器 #Modbus #IFix #lstm #智慧城市 #ROS #海外短剧 #海外短剧app开发 #海外短剧系统开发 #短剧APP #短剧APP开发 #短剧系统开发 #海外短剧项目 #Cpolar #国庆假期 #服务器告警 #跨域 #发布上线后跨域报错 #请求接口跨域问题解决 #跨域请求代理配置 #request浏览器跨域 #anaconda #虚拟环境 #fpga开发 #LVDS #高速ADC #DDR #游戏机 #JumpServer #UDP的API使用 #Node.js #漏洞检测 #CVE-2025-27210 #Modbus-TCP #振镜 #振镜焊接 #azure #FRP #ai编程 #编辑器 #远程连接 #ida #SRS #流媒体 #直播 #研发管理 #禅道 #禅道云端部署 #glibc #中间件 #xeon #ONLYOFFICE #MCP 服务器 #zabbix #UDP套接字编程 #UDP协议 #网络测试 #RAID #RAID技术 #磁盘 #存储 #mapreduce #maven #Nacos #微服务 #SSE #STUN # TURN # NAT穿透 #蓝牙 #LE Audio #BAP #三种参数 #参数的校验 #fastAPI #unity3d #服务器框架 #Fantasy #xlwings #Excel #pytest #目标检测 #YOLO26 #YOLO11 #llm #计算机 #连锁药店 #连锁店 #工业级串口服务器 #串口转以太网 #串口设备联网通讯模块 #串口服务器选型 #visual studio code #prompt #mamba #凤希AI伴侣 #Ubuntu #Steam #饥荒联机版 #CMake #Make #C/C++ #Python #零代码平台 #AI开发 #paddleocr #命令模式 #Spring AI #STDIO协议 #Streamable-HTTP #McpTool注解 #服务器能力 # 高并发部署 #pencil #pencil.dev #设计 #visual studio #CNAS #CMA #程序文件 #vps #图像处理 #yolo #Anything-LLM #IDC服务器 #工具集 #CPU #监测 #敏捷流程 #esp32教程 #行为模式分析 #数据 #应用层 #跨领域 #敏感信息 #模版 #函数 #类 #笔试 #排序 #sqlite #LabVIEW知识 #LabVIEW程序 #labview #LabVIEW功能 #ipv6 #Playbook #AI服务器 #WEB #simulink #aiohttp #asyncio #异步 #高品质会员管理系统 #收银系统 #同城配送 #最好用的电商系统 #最好用的系统 #推荐的前十系统 #JAVA PHP 小程序 #软件 #本地生活 #电商系统 #商城 #p2p #intellij-idea #database #idea #学术写作辅助 #论文创作效率提升 #AI写论文实测 #Triton #AI助手 #企业微信集成 #轻量大模型 #list #海外服务器安装宝塔面板 #翻译 #开源工具 #echarts #Rust #910B #SSH保活 #Miniconda #远程开发 ##程序员和算法的浪漫 #rdp #SMP(软件制作平台) #EOM(企业经营模型) #应用系统 #NAS #飞牛NAS #监控 #NVR #EasyNVR #项目申报系统 #项目申报管理 #项目申报 #企业项目申报 #wpf #JAVA #Java #openlayers #bmap #tile #server #vue #ue4 #ue5 #DedicatedServer #独立服务器 #专用服务器 #语义搜索 #嵌入模型 #Qwen3 #AI推理 #虚拟机 #EMC存储 #存储维护 #NetApp存储 #简单数论 #埃氏筛法 #openEuler #Hadoop #客户端 #DIY机器人工房 #vuejs # GLM-4.6V-Flash-WEB # 显卡驱动备份 #联机教程 #局域网联机 #局域网联机教程 #局域网游戏 #yolov12 #研究生life #Shiro #反序列化漏洞 #CVE-2016-4437 #nacos #银河麒麟aarch64 #uvicorn #uvloop #asgi #event #运营 #React安全 #漏洞分析 #Next.js #信令服务器 #Janus #MediaSoup #职场发展 #embedding #高仿永硕E盘的个人网盘系统源码 #阳台种菜 #园艺手扎 #Gemini #Nano Banana Pro #Jetty # CosyVoice3 # 嵌入式服务器 #汽车 #群晖 #音乐 #ip #typescript #npm #VPS #搭建 #土地承包延包 #领码SPARK #aPaaS+iPaaS #数字化转型 #智能审核 #档案数字化 #可撤销IBE #服务器辅助 #私钥更新 #安全性证明 #双线性Diffie-Hellman #状态模式 #智能体 #空间计算 #原型模式 #SMTP # 内容安全 # Qwen3Guard #X11转发 #MS #Materials #clickhouse #代理 #Moltbot #5G #平板 #交通物流 #智能硬件 #2026AI元年 #年度趋势 #国产PLM #瑞华丽PLM #瑞华丽 #PLM # 远程访问 # 服务器IP配置 #捷配 #pcb工艺 # AI翻译机 # 实时翻译 #apache #r-tree #心理健康服务平台 #心理健康系统 #心理服务平台 #心理健康小程序 #区间dp #二进制枚举 #图论 #北京百思可瑞教育 #百思可瑞教育 #北京百思教育 #多线程 #性能调优策略 #双锁实现细节 #动态分配节点内存 #markdown #建站 #自动化运维 #跳槽 #业界资讯 #IO #google #search #插件 #ms-swift # 一锤定音 # 大模型微调 #deepseek #VibeVoice # 语音合成 #DDD #tdd #risc-v #密码 #cpp #交互 #CUDA #Docker #策略模式 #dba #SSH公钥认证 # 安全加固 #K8s #镜像 #集群自动化 #dynadot #域名 #Fun-ASR # 语音识别 # WebUI #RustDesk # IndexTTS 2.0 # 远程运维 #性能测试 #LoadRunner #bytebase #NPU #CANN #TFTP #工厂模式 #Qwen3-14B # 大模型部署 # 私有化AI #tensorflow #wps #log #screen 命令 #运维开发 #opc ua #opc #大剑师 #nodejs面试题 #vp9 #Moltbook #Clawdbot #AutoDL #安全架构 #浏览器自动化 #python #支付 #PyTorch 特性 #动态计算图 #张量(Tensor) #自动求导Autograd #GPU 加速 #生态系统与社区支持 #与其他框架的对比 #指针 #cascadeur #设计师 #远程桌面 #远程控制 # GLM-TTS # 数据安全 #SEO优化 #chrome #SSH免密登录 #bash #Gunicorn #WSGI #Flask #并发模型 #容器化 #性能调优 #ceph #集成测试 #静脉曲张 #腿部健康 #源代码管理 #spring native #智能一卡通 #门禁一卡通 #梯控一卡通 #电梯一卡通 #消费一卡通 #一卡通 #考勤一卡通 #远程访问 #远程办公 #飞网 #安全高效 #配置简单 # 目标检测 #chat #RK3576 #瑞芯微 #硬件设计 #css3 #SAP #ebs #metaerp #oracle ebs #逆向工程 #ngrok #SSH跳转 #社交智慧 #职场生存 #系统思维 #身体管理 #商务宴请 #拒绝油腻 #清醒日常 # IndexTTS # GPU集群 #框架搭建 #iot #智能家居 #Spring #Spring Boot #RPA #影刀RPA #AI办公 #C语言 #vivado license #jupyter #galeweather.cn #高精度天气预报数据 #光伏功率预测 #风电功率预测 #高精度气象 #WinSCP 下载安装教程 #SFTP #FTP工具 #服务器文件传输 #个人博客 #媒体 #健康医疗 #教育电商 #Anaconda配置云虚拟环境 #mybatis #贴图 #材质 #可信计算技术 #爱心代码 #表白代码 #爱心 #tkinter #情人节表白代码 #winscp #go #嵌入式编译 #ccache #distcc #测评 # 双因素认证 #powerbi #JT/T808 #车联网 #车载终端 #模拟器 #仿真器 #开发测试 #nas #音乐分类 #音频分析 #ViT模型 #Gradio应用 #鼠大侠网络验证系统源码 #AI赋能盾构隧道巡检 #开启基建安全新篇章 #以注意力为核心 #YOLOv12 #AI隧道盾构场景 #盾构管壁缺陷病害异常检测预警 #隧道病害缺陷检测 #cursor #puppeteer #spine #GLM-4.6V-Flash-WEB # AI视觉 # 本地部署 #进程创建与终止 #鸿蒙系统 #系统安全 #车载系统 #Deepseek #gpt-3 #ARM64 # DDColor # ComfyUI #bootstrap #Fluentd #Sonic #日志采集 #IndexTTS 2.0 #本地化部署 #YOLOv8 # Docker镜像 #文件IO #输入输出流 #tcpdump #企业架构治理 #电力企业IT架构 #IT架构设计 #IndexTTS2 # 阿里云安骑士 # 木马查杀 #excel #Karalon #AI Test #迁移重构 #数据安全 #代码迁移 #车辆排放 #restful #ajax #转行 #SA-PEKS # 关键词猜测攻击 # 盲签名 # 限速机制 #Claude #视频去字幕 #flume #外卖配送 #处理器模块 #现货库存 #价格优惠 #PM864AK01 #3BSE018161R1 #控制器模块 #图像识别 #实在Agent #UDP #榛樿鍒嗙被 #工程实践 #pve #CLI #JavaScript #langgraph.json #ambari #bigtop #hdp #hue #kerberos #OPCUA #raid #raid阵列 #KMS激活 #gpt #API #taro #OSS #欧拉 #CSDN #分库分表 #垂直分库 #水平分表 #雪花算法 #分布式ID #跨库查询 #Syslog #系统日志 #日志分析 #日志监控 #生产服务器问题查询 #日志过滤 # 硬件配置 #思维模型 #认知框架 #认知 #算力一体机 #ai算力服务器 #YOLOFuse # 水冷服务器 # 风冷服务器 #VoxCPM-1.5-TTS # 云端GPU # PyCharm宕机 #青少年编程 #webpack #儿童AI #图像生成 #考试系统 #在线考试 #培训考试 #考试练习 #挖漏洞 #渗透测试 #黑客技术 #攻击溯源 #编程 #寄存器 #stl #漏洞修复 #IIS Crypto #blender #warp #vrrp #脑裂 #keepalived主备 #高可用主备都持有VIP #coffeescript #材料工程 #智能电视 #mariadb #软件需求 #AI生成 # outputs目录 # 自动化 #H3C #esp32 arduino #HistoryServer #Spark #YARN #jobhistory #FASTMCP #sglang #ZooKeeper #ZooKeeper面试题 #面试宝典 #深入解析 #大模型部署 #mindie #大模型推理 #ComfyUI # 推理服务器 #知识库 #libosinfo #Go并发 #高并发架构 #Goroutine #系统设计 #Dify #鲲鹏 #tornado #net core #kestrel #web-server #asp.net-core #elk #模拟退火算法 #vmware #三维重建 #高斯溅射 #postman #reactjs #UEFI #BIOS #Legacy BIOS #产品运营 #内存接口 # 澜起科技 # 服务器主板 #Puppet # IndexTTS2 # TTS #Aluminium #Google #学工管理系统 #学工一体化平台 #学工软件二次开发 #学工平台定制开发 #学工系统服务商 #学工系统源头厂家 #智慧校园学工系统 #tcp/ip #网络 #文件传输 #电脑文件传输 #电脑传输文件 #电脑怎么传输文件到另一台电脑 #电脑传输文件到另一台电脑 #说话人验证 #声纹识别 #CAM++ #云开发 #性能 #优化 #RAM #KMS 激活 #AI智能棋盘 #Rock Pi S #wireshark #x86_64 #数字人系统 #MC群组服务器 #因果学习 #网络攻击模型 # 服务器迁移 # 回滚方案 #windows11 #系统修复 #cocoa #BoringSSL #Tetrazine-Acid #1380500-92-4 #1panel #PTP_1588 #gPTP #gitea #rtsp #转发 #unix #CS2 #debian13 #eclipse #Windows #汇编 #turn #ICE #信创国产化 #达梦数据库 #视觉检测 #RXT4090显卡 #RTX4090 #深度学习服务器 #硬件选型 # ARM服务器 # 鲲鹏 #IntelliJ IDEA #neo4j #NoSQL #SQL #http头信息 #Llama-Factory # 大模型推理 #Coturn #k8s #xss # 代理转发 #idm #网站 #截图工具 #批量处理图片 #图片格式转换 #图片裁剪 #进程等待 #wait #waitpid #树莓派 #温湿度监控 #WhatsApp通知 #IoT #MySQL # 服务器IP # 端口7860 # 离线AI #万悟 #联通元景 #TCP服务器 #开发实战 #claude-code #软件开发 #SMARC #ARM #农产品物流管理 #物流管理系统 #农产品物流系统 #农产品物流 #ThingsBoard MCP #Kylin-Server #国产操作系统 #服务器安装 #VSCode # SSH #Android16 #音频性能实战 #音频进阶 #短剧 #短剧小程序 #短剧系统 #微剧 #LangFlow # 智能运维 # 性能瓶颈分析 # GPU租赁 # 自建服务器 #hibernate #nosql # 云服务器 #健身房预约系统 #健身房管理系统 #健身管理系统 #web服务器 #文件上传漏洞 #未加引号服务路径 #bug #网络编程 #I/O模型 #并发 #水平触发、边缘触发 #多路复用 #创业管理 #财务管理 #团队协作 #创始人必修课 #数字化决策 #经营管理 #卷积神经网络 #CTF #dash #gateway #Comate #遛狗 #C++ UA Server #SDK #跨平台开发 #聊天小程序 #arm64 #SSH复用 # 远程开发 #结构与算法 #扩展屏应用开发 #android runtime #服务器解析漏洞 #nodejs #云服务器选购 #Saas #域名注册 #新媒体运营 #网站建设 #国外域名 #TLS协议 #HTTPS #运维安全 #UOS #海光K100 #统信 #NFC #智能公交 #服务器计费 #FP-增长 #outlook #错误代码2603 #无网络连接 #2603 #easyui #mssql #注入漏洞 #大学生 #大作业 #MOXA #GATT服务器 #蓝牙低功耗 #safari # GPU服务器 # tmux #具身智能 #练习 #基础练习 #循环 #九九乘法表 #计算机实现 #esp32 #mosquito #esb接口 #走处理类报异常 #效率神器 #办公技巧 #自动化工具 #Windows技巧 #打工人必备 #le audio #低功耗音频 #通信 #连接 #部署 #昇腾300I DUO #智能体从0到1 #新手入门 #docker-compose #smtp #smtp服务器 #PHP #intellij idea #vnstat #c++20 # 远程连接 #数字孪生 #三维可视化 # Qwen3Guard-Gen-8B #SQL调优 #EXPLAIN #慢查询日志 #分布式架构 #后端开发 #fs7TF #N8N #cosmic #kmeans #昇腾 #npu #晶振 #WinDbg #Windows调试 #内存转储分析 #攻防演练 #Java web #红队 #随机森林 #ansys #ansys问题解决办法 #黑群晖 #无U盘 #纯小白 #运维 #GB28181 #SIP信令 #SpringBoot #视频监控 #远程软件 #SSH跳板机 # Python3.11 #WT-2026-0001 #QVD-2026-4572 #smartermail #AI视频创作系统 #AI视频创作 #AI创作系统 #AI视频生成 #AI工具 #AI创作工具 #东方仙盟 #夏天云 #夏天云数据 #hdfs #API限流 # 频率限制 # 令牌桶算法 #华为od #华为od机试 #华为od机考 #华为od最新上机考试题库 #华为OD题库 #华为OD机试双机位C卷 #od机考题库 #AI+ #coze #AI入门 #AI赋能 #TTS私有化 # 音色克隆 #处理器 #计组 #数电 #视频 #分布式数据库 #集中式数据库 #业务需求 #选型误 # Connection refused #Python3.11 #teamviewer #蓝湖 #Axure原型发布 #知识图谱 #React #Next #CVE-2025-55182 #RSC #Apple AI #Apple 人工智能 #FoundationModel #Summarize #SwiftUI #clawdbot #上下文工程 #langgraph #意图识别 #门禁 #梯控 #智能梯控 #单例模式 #Socket网络编程 #工作 #快递盒检测检测系统 #网安应急响应 #QQbot #QQ #微PE # GLM # 服务连通性 #WRF #WRFDA #百度 #HarmonyOS #数据采集 #浏览器指纹 #muduo库 #vertx #vert.x #vertx4 #runOnContext #uv #uvx #uv pip #npx #Ruff # 服务器配置 # GPU # 高并发 #ESP32 #传感器 #MicroPython #数据恢复 #视频恢复 #视频修复 #RAID5恢复 #流媒体服务器恢复 #web server #请求处理流程 #gRPC #注册中心 #Tokio #异步编程 #系统编程 #Pin #http服务器 #AutoDL使用教程 #AI大模型训练 #linux常用命令 #PaddleOCR训练 #edge #迭代器模式 #观察者模式 #机器人学习 #服务器开启 TLS v1.2 #IISCrypto 使用教程 #TLS 协议配置 #IIS 安全设置 #服务器运维工具 #CosyVoice3 # IP配置 # 0.0.0.0 # 轻量化镜像 # 边缘计算 #网络配置实战 #Web/FTP 服务访问 #计算机网络实验 #外网访问内网服务器 #Cisco 路由器配置 #静态端口映射 #网络运维 #milvus #防火墙 #CVE-2025-68143 #CVE-2025-68144 #CVE-2025-68145 #Socket #套接字 #I/O多路复用 #字节序 #html5 #服务器架构 #AI推理芯片 #weston #x11 #x11显示服务器 # 批量部署 #copilot #RSO #机器人操作系统 # TTS服务器 # 键鼠锁定 #mtgsig #美团医药 #美团医药mtgsig #美团医药mtgsig1.2 #opc模拟服务器 #MQTT协议 #服务器线程 # SSL通信 # 动态结构体 #政务 #语音生成 #TTS #集成学习 #证书 #勒索病毒 #勒索软件 #加密算法 #.bixi勒索病毒 #数据加密 # 大模型 # ms-swift #CA证书 #星际航行 #个人助理 #数字员工 #JNI #agentic bi #论文复现 #sql注入 # 数字人系统 # 远程部署 #Host #SSRF #知识 #科普 #rustdesk #可再生能源 #绿色算力 #风电 #连接数据库报错 #麦克风权限 #访问麦克风并录制音频 #麦克风录制音频后在线播放 #用户拒绝访问麦克风权限怎么办 #uniapp 安卓 苹果ios #将音频保存本地或上传服务器 #华为od机考真题 #华为od机试真题 #华为OD上机考试真题 #华为OD上机考试双机位C卷 #华为ODFLASH坏块监测系统 #osg #漏洞挖掘 #Exchange #sentinel #KMS #slmgr #娱乐 #计算机毕业设计 #程序定制 #毕设代做 #课设 #宝塔面板部署RustDesk #RustDesk远程控制手机 #手机远程控制 #AI技术 #安全威胁分析 #学术生涯规划 #CCF目录 #基金申请 #职称评定 #论文发表 #科研评价 #顶会顶刊 #源码 #闲置物品交易系统 #TRO #TRO侵权 #TRO和解 #仙盟创梦IDE #运维工具 # Base64编码 # 多模态检测 #IPv6 #DNS #动态规划 #Discord机器人 #云部署 #程序那些事 #cocos2d #图形渲染 #dlms #dlms协议 #逻辑设备 #逻辑设置间权限 #AI Agent #开发者工具 #SPA #单页应用 #web3.py #IT #技术 #Minecraft #Minecraft服务器 #PaperMC #我的世界服务器 #ipmitool #BMC # 黑屏模式 #前端开发 #节日 #EN4FE #ESP32编译服务器 #Ping #DNS域名解析 #Kuikly #openharmony #C #领域驱动 #moltbot #自由表达演说平台 #演说 #移动端h5网页 #调用浏览器摄像头并拍照 #开启摄像头权限 #拍照后查看与上传服务器端 #摄像头黑屏打不开问题 #nfs #iscsi #地理 #遥感 #reactor反应堆 #面向对象 #麒麟OS #文件管理 #文件服务器 #国产开源制品管理工具 #Hadess #一文上手 # REST API #swagger #kong #Kong Audio #Kong Audio3 #KongAudio3 #空音3 #空音 #中国民乐 #范式 # keep-alive #入侵 #日志排查 #ET模式 #非阻塞 #高并发服务器 # 模型训练 #clamav #AI应用 #语义检索 #向量嵌入 #多进程 #python技巧 #高考 #企业级存储 #网络设备 #多模态 #微调 #超参 #LLamafactory #Smokeping #智能体来了 #传统行业 #GPU #租显卡 #训练推理 #Linux多线程 #Java程序员 #Java面试 #Spring源码 #zotero #WebDAV #同步失败 #代理模式 #轻量化 #低配服务器 #麒麟 #V11 #kylinos #人脸活体检测 #live-pusher #动作引导 #张嘴眨眼摇头 #苹果ios安卓完美兼容 #大模型应用 #API调用 #PyInstaller打包运行 #服务端部署 #gnu #glances #duckdb #强化学习 #策略梯度 #REINFORCE #蒙特卡洛 #ueditor导入word #STL #string #信息收集 #Langchain-Chatchat # 国产化服务器 # 信创 #Autodl私有云 #深度服务器配置 #.netcore # 自动化运维 #阿里云RDS # 模型微调 #cesium #可视化 #LED #设备树 #GPIO #实体经济 #商业模式 #数智红包 #商业变革 #创业干货 #VMware创建虚拟机 #m3u8 #HLS #移动端H5网页 #APP安卓苹果ios #监控画面 直播视频流 #Zabbix #语音合成 #n8n解惑 #C₃₂H₄₅N₇O₁₁S₂ #身体实验室 #健康认知重构 #微行动 #NEAT效应 #亚健康自救 #ICT人 #Qwen3-VL # 服务状态监控 # 视觉语言模型 #eureka #广播 #组播 #并发服务器 #全栈 #企业存储 #RustFS #对象存储 #高可用 #三维 #3D #云计算运维 #asp.net上传大文件 #传媒 #隐函数 #常微分方程 #偏微分方程 #线性微分方程 #线性方程组 #非线性方程组 #复变函数 #c++高并发 #百万并发 #Termux #Samba #模块 #UDP服务器 #recvfrom函数 #CVE-2025-61686 #路径遍历高危漏洞 #uip #计算机现代史 #webgl ##租显卡 #Ward #IPMI #高精度农业气象 #全文检索 #递归 #线性dp #银河麒麟服务器系统 #4U8卡 AI 服务器 ##AI 服务器选型指南 #GPU 互联 #GPU算力 #ShaderGraph #图形 #日志模块 #VMware Workstation16 #服务器操作系统 #devops #音诺ai翻译机 #AI翻译机 # Ampere Altra Max #sklearn #文本生成 #CPU推理 #VMWare Tool #MinIO服务器启动与配置详解 #数据访问 #ueditor导入pdf #H5网页 #网页白屏 #H5页面空白 #资源加载问题 #打包部署后网页打不开 #HBuilderX #A2A #GenAI #DHCP #网络安全大赛 #xml #磁盘配额 #存储管理 #形考作业 #国家开放大学 #系统运维 #DAG #投标 #标书制作 #实时检测 #程序开发 #程序设计 #b树 #mvc #idc #SSH密钥 # ControlMaster #题解 #图 #dijkstra #迪杰斯特拉 #HarmonyOS APP #智能制造 #供应链管理 #工业工程 #库存管理 #AI电商客服 #量子计算 #memory mcp #Cursor #数据可视化 #网路编程 #NSP #下一状态预测 #aigc #声源定位 #MUSIC #Buck #NVIDIA #交错并联 #DGX #旅游 #RK3588 #RK3588J #评估板 #核心板 #嵌入式开发 #经济学 #zygote #应用进程 #gerrit #AI 推理 #NV #memcache #ServBay #C2000 #TI #实时控制MCU #AI服务器电源 #提词器 #西门子 #汇川 #Blazor # 树莓派 # ARM架构 #resnet50 #分类识别训练 # 网络延迟 #SSH代理转发 #ranger #MySQL8.0 #OpenManage # OTA升级 # 黄山派 #内网 #screen命令 #企业微信机器人 #本地大模型 #智能体对传统行业冲击 #行业转型 #系统管理 #服务 #Xshell #Finalshell #生物信息学 #组学 #Spire.Office #隐私合规 #网络安全保险 #法律风险 #风险管理 #代理服务器 #雨云服务器 #教程 #MCSM面板 #claudeCode #content7 #超时设置 #客户端/服务器 #挖矿 #Linux病毒 #管道Pipe #system V #统信UOS #win10 #qemu #odoo #muduo #TcpServer #accept #公共MQTT服务器 #appche #0day漏洞 #DDoS攻击 #漏洞排查 #懒汉式 #恶汉式 #win11 #ftp #sftp #uniapp #合法域名校验出错 #服务器域名配置不生效 #request域名配置 #已经配置好了但还是报错 #uniapp微信小程序 #AI-native # DIY主机 # 交叉编译 #国产化OS #华为机试 #OpenHarmony #Redis #分布式锁 #工程设计 #预混 #扩散 #燃烧知识 #层流 #湍流 #计算几何 #斜率 #方向归一化 #叉积 #视觉理解 #Moondream2 #多模态AI #samba #c # 批量管理 #ASR #SenseVoice #硬盘克隆 #DiskGenius #路由器 #PN 结 #ArkUI #ArkTS #鸿蒙开发 #node #超算中心 #PBS #lsf #反向代理 #报表制作 #职场 #用数据讲故事 #CS336 #Assignment #Experiments #TinyStories #Ablation #手机h5网页浏览器 #安卓app #苹果ios APP #手机电脑开启摄像头并排查 #实时音视频 #pxe #CCE #Dify-LLM #Flexus #参数估计 #矩估计 #概率论 #MCP服务器注解 #异步支持 #方法筛选 #声明式编程 #自动筛选机制 #余行补位 #意义对谈 #余行论 #领导者定义计划 #MinIO #ARMv8 #内存模型 #内存屏障 #gmssh #宝塔 #AE #系统安装 #铁路桥梁 #DIC技术 #箱梁试验 #裂纹监测 #四点弯曲 #运动 #AITechLab #cpp-python #CUDA版本 #POC #问答 #交付 #pyqt #AI应用编程 #r语言 #设计规范 #放大电路 #服务器IO模型 #非阻塞轮询模型 #多任务并发模型 #异步信号模型 #多路复用模型 #STDIO传输 #SSE传输 #WebMVC #WebFlux #边缘AI # Kontron # SMARC-sAMX8 #游戏服务器断线 #期刊 #SCI #基础语法 #标识符 #常量与变量 #数据类型 #运算符与表达式 #Archcraft #remote-ssh #小艺 #搜索 #Spring AOP #Linly-Talker # 数字人 # 服务器稳定性 #百度文库 #爱企查 #旋转验证码 #验证码识别 #scanf #printf #getchar #putchar #cin #cout #主板 #总体设计 #电源树 #框图 #OpenAI #故障 #电子电气架构 #系统工程与系统架构的内涵 #Routine #starrocks #Beidou #北斗 #SSR #Taiji #poll #numpy #格式工厂 #L6 #L10 #L9 #docker安装seata #composer #symfony #java-zookeeper # AI部署 #人脸识别sdk #视频编解码 #远程更新 #缓存更新 #多指令适配 #物料关联计划 #Prometheus #决策树 #二值化 #Canny边缘检测 #轮廓检测 #透视变换 #DooTask #防毒面罩 #防尘面罩 #编程助手 #交换机 #三层交换机 #个性化推荐 #BERT模型 #proc #开关电源 #热敏电阻 #PTC热敏电阻 #pipeline #Transformers #NLP #个人电脑 #AI运维 #DevOps自动化 # 权限修复 #SQL注入主机 #一人公司 #独立开发者 #思爱普 #SAP S/4HANA #ABAP #NetWeaver #戴尔服务器 #戴尔730 #装系统 #junit #WAN2.2 #vncdotool #链接VNC服务器 #如何隐藏光标 #人形机器人 #人机交互 #FHSS #EventLoop #统信操作系统 #lucene #字符串 #时间复杂度 #空间复杂度 #算力建设 #电梯 #电梯运力 #电梯门禁 #数据报系统 #ETL管道 #向量存储 #数据预处理 #DocumentReader #bond #服务器链路聚合 #网卡绑定 #spring ai #oauth2 #nmodbus4类库使用教程 # 高温监控 #编程语言 # 环境迁移 #江协 #瑞萨 #OLED屏幕移植 #图像分类 #图像分割 #yolo26算法 #AI工具集成 #容器化部署 #2025年 #AI教程 #Matrox MIL #二次开发 #CMC # 串口服务器 # NPort5630 #Gateway #认证服务器集成详解 #一周会议与活动 #ICLR #CCF #自动化巡检 #cpu #istio #服务发现 #后端框架 #RWK35xx #语音流 #实时传输 #SEW #赛威 #SEW变频器 #adobe #数据迁移 #rag #express #cherry studio # child_process #ossinsight #free #vmstat #sar #scikit-learn #canvas层级太高 #canvas遮挡问题 #盖住其他元素 #苹果ios手机 #安卓手机 #调整画布层级 #测速 #iperf #iperf3 #小智 #分子动力学 #化工仿真 #okhttp #api #key #AI作画 #人大金仓 #Kingbase #boltbot #tekton #DuckDB #协议 #Arduino BLDC #核辐射区域探测机器人 #xshell #host key #rsync # 数据同步 #YOLO识别 #YOLO环境搭建Windows #YOLO环境搭建Ubuntu #Python办公自动化 #Python办公 #基金 #股票 #jquery #fork函数 #进程创建 #进程终止 #session #计算机外设 #JADX-AI 插件