当客户端使用 JWT(JSON Web Token)访问服务器时,服务器需要在每次请求时对客户端提供的 JWT 进行校验。这是 JWT 基于无状态认证的核心工作原理之一。

具体原因:

  1. JWT 是无状态的
    JWT 是无状态的,服务器不需要保存每个客户端的会话状态。客户端每次发送请求时,都会携带 JWT,服务器通过校验 JWT 来验证用户身份。因此,服务器需要在每次请求中对 JWT 进行校验,以确保请求是来自合法用户。

  2. 校验的关键步骤

    • 签名校验:服务器会使用事先约定好的秘钥来校验 JWT 的签名,以验证该 Token 没有被篡改。
    • 有效期校验:JWT 通常包含 exp(过期时间)字段,服务器需要检查 Token 是否已经过期。
    • 其他字段校验:JWT 还可能包含其他信息(如用户权限、角色等),服务器可以根据这些信息执行进一步的验证。

JWT 校验步骤通常包括:

  1. 解析 Token:服务器从请求头或其他位置(如请求体、查询参数)提取 JWT。
  2. 校验签名:使用服务器的私钥或共享秘钥来校验 JWT 的签名,确保 Token 没有被篡改。
  3. 校验有效期:检查 exp 字段,确保 Token 没有过期。
  4. 校验其他声明(claims):如 iss(签发者)、aud(接收者)等,确保这些信息符合预期。

示例:

假设客户端在 Authorization 请求头中发送 JWT:

Authorization: Bearer <JWT_TOKEN>

服务器端在每次收到请求时,都需要进行校验,例如:

func validateJWT(tokenString string) error {
    // 解析和验证 JWT
    token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
        // 验证签名方法是否正确
        if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
            return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
        }
        // 返回用于签名验证的密钥
        return []byte("your-256-bit-secret"), nil
    })

    if err != nil {
        return err
    }

    // 校验 claims 里的 exp 是否过期
    if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
        exp := claims["exp"].(float64)
        if time.Now().Unix() > int64(exp) {
            return fmt.Errorf("token is expired")
        }
        return nil
    }
    return fmt.Errorf("invalid token")
}

为什么每次请求都需要校验?

  • 无状态的安全性:JWT 是无状态的,这意味着服务器不保存会话数据,因此每次请求服务器都需要从 JWT 中获取信息并校验,以防止伪造和篡改。
  • 可能的风险:如果不每次校验 JWT,攻击者可能利用过期或伪造的 JWT 发起攻击,危害应用的安全性。

总结:

每次请求时,服务器需要对客户端传来的 JWT 进行校验,以确保 Token 的合法性、安全性和有效性。这是确保无状态认证系统安全的重要一环。