安全:什么是 Token(令牌)?

一. Token 的英文本义 和 常见令牌

Token 英文本义为“券、信物”,在计算机领域,我们翻译成“令牌”。其实就是“信物”的意思。我们看影视剧中,主角手握令牌,就可以过城门、进皇宫、领取装备等等。我们在计算机领域中,谁有了有效的 token,谁 就有了临时获取数据的身份,所以 token 翻译成“令牌”,更加的生动。

token 在计算机领域,核心 就是 “available”,我们常见的令牌如下:

  1. 认证令牌(Authentication Token)
    认证令牌是用于验证用户身份的一种机制。当用户登录系统后,服务器端会生成一个唯一的认证令牌,并将其发给用户。用户在随后的请求中附带这个令牌,以此来证明自己的身份。这种机制常用于网络应用,帮助维持用户会话或实现无状态的身份验证。

  2. 网络令牌(Network Token)
    在网络协议中,令牌可以指代控制访问或数据传输的权利。例如,在令牌环网络中,令牌是一个特殊的数据包,只有持有令牌的计算机才能发送数据,从而避免数据碰撞。

  3. 数字货币和区块链中的Token
    在区块链和数字货币领域,Token通常指代在特定区块链上发行的数字资产或代币。这些Token可以代表各种资产,如货币、股份、资产等,且可以在区块链上自由交易。

不同类型的Token在不同的领域和应用场景中扮演着重要角色,但核心都是表示一种可以临时获取数据的身份或资格。我们这里着重的就是讲述的是“认证令牌”。

二. 认证令牌的由来

token 出现前

我们以前设计 登录系统,过程是:

1、客户端通过 用户名和密码登录服务器。

2、服务端收到请求,去验证用户名与密码。验证成功,在当前对话(session)里面保存相关数据,比如用户角色、登录时间等等。

3、服务器向用户返回一个 session_id,写入客户端的 Cookie。

4、客户端随后的每一次请求,都会通过 Cookie,将 session_id 传回服务器。

5、服务器收到 session_id,获取相应的session, 来判断是否通过客户端的请求。

这种验证方式有很多问题,比如,现代系统都是分布式系统,session 无法跨系统共享。

token 出现后

1、客户端使用用户名跟密码请求登录;

2、服务端收到请求,去验证用户名与密码;验证成功,服务端会签发一个Token,然后再把这个 Token 发送给客户端;

3、客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里;

4、客户端每次向服务端请求资源的时候需要带着服务端签发的 Token;

5、服务端收到请求,验证密客户端请求里面带着的 Token, 如果验证成功,就继续执行客户端请求的业务逻辑,否则就是验证失败报错返回给客户端;

三. 基本概念

在 Java 开发中,Token(令牌) 通常指一串经过加密或编码的字符串,作为客户端与服务器之间进行身份验证、信息传递或权限校验的 “凭证”。它本质上是一种轻量级的身份标识,用于替代传统的 Session 机制,尤其在分布式系统、前后端分离架构或跨域场景中广泛使用。

四. Token 的核心作用:

  • 身份验证:用户登录成功后,服务器生成一个 Token 并返回给客户端,客户端后续请求时携带该 Token,服务器通过验证 Token 有效性来确认用户身份,无需重复登录。
  • 信息传递:Token 可包含少量非敏感用户信息(如用户 ID、角色),减少服务器查询数据库的次数。
  • 权限校验:Token 中可嵌入权限信息,服务器通过解析 Token 直接判断用户是否有权限访问某个接口。
  • 无状态性:服务器无需存储 Token 相关数据(对比 Session 需要服务器保存会话状态),更适合分布式系统(如微服务架构)。

五. Java 中常见的 Token 场景:

1. JWT(JSON Web Token):

最常用的 Token 格式之一,由三部分组成(头部 Header + 载荷 Payload + 签名 Signature),采用 JSON 格式存储信息,可自包含、可验证。
例如:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkiLCJuYW1lIjoiSm9obiBEb2UifQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

2. OAuth2.0 令牌:

在第三方授权场景中(如微信登录、GitHub 授权),服务器会颁发 Access Token 或 Refresh Token,用于访问第三方资源。

3.自定义令牌:

开发者可自行设计 Token 格式(如 UUID 加盐加密),但安全性和通用性通常不如 JWT。
Java 中处理 Token 的常见方式:
以 JWT 为例,Java 中常用库(如 jjwt、java-jwt)可快速实现 Token 的生成与验证:


/* 引入依赖(Maven)
 <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>
   <!-- 可选:JSON 处理模块(若用默认序列化需添加) -->
   <dependency>
       <groupId>io.jsonwebtoken</groupId>
       <artifactId>jjwt-jackson</artifactId>
       <version>0.11.5</version>
       <scope>runtime</scope>
   </dependency>
*/

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import java.security.Key;
import java.util.Date;

public class JwtExample {
    // 生成签名密钥(实际开发中需妥善保管,避免泄露)
    private static final Key SECRET_KEY = Keys.secretKeyFor(SignatureAlgorithm.HS256);
    // Token 过期时间(1小时)
    private static final long EXPIRATION_TIME = 3600000;

    // 生成 Token
    public static String generateToken(String userId, String username) {
        return Jwts.builder()
                .setSubject(userId) // 主题(通常为用户ID)
                .claim("username", username) // 自定义信息
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) // 过期时间
                .signWith(SECRET_KEY) // 签名
                .compact();
    }

    // 验证并解析 Token
    public static void validateToken(String token) {
        try {
            Jwts.parserBuilder()
                    .setSigningKey(SECRET_KEY)
                    .build()
                    .parseClaimsJws(token); // 验证签名和过期时间
            System.out.println("Token 有效");
        } catch (Exception e) {
            System.out.println("Token 无效:" + e.getMessage());
        }
    }

    public static void main(String[] args) {
        String token = generateToken("123", "张三");
        System.out.println("生成的 Token:" + token);
        validateToken(token); // 验证 Token
    }
}

六. 优势总结:

  • 无状态:服务器无需存储会话信息,减轻分布式系统的同步压力。
  • 跨域支持:适合前后端分离(如 Vue/React 前端 + Java 后端)或跨服务调用。
  • 扩展性:可灵活嵌入用户信息,减少数据库查询。
    在 Java 开发中,Token 是实现身份认证和权限控制的核心手段,尤其在 Spring Security、微服务架构中应用广泛。

题外话:

既然有了令牌,就有了权限、身份。它的作用这么大,那肯定需要防伪,所以令牌 需要 签名 来防伪(或者说认证)。签名的内容点击“这里

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值