【JWT】jwt认证机制认识与理解,go案例实现

JWT 认证机制

JWT(JSON Web Token)是一种轻量级的身份认证机制,广泛应用于现代 Web 开发中,尤其是在分布式系统和微服务中。它通过签名技术确保数据的真实性和完整性。


1. JWT 的基本结构

JWT 是一个由三部分组成的字符串(头部,负载,签名):

Header.Payload.Signature
1.1 Header(头部)
  • 作用:声明 Token 的元信息,如签名算法和 Token 类型。
  • 典型结构
    {
      "alg": "HS256", // 签名算法,如 HMAC SHA256
      "typ": "JWT"    // Token 类型
    }
    
  • Base64 编码:经过 Base64 编码后,生成 Header 部分。
1.2 Payload(负载)
  • 作用
  • Payload 部分是一个 JSON 对象,用来存放实际需要传递的数据。
  • 存储声明(claims),包括用户信息和元数据。
  • 三种声明分类
    • 注册声明(Registered Claims)
      标准字段,JWT 规定了7个官方字段,供选用。
      • iss (issuer):签发人
      • exp (expiration time):过期时间
      • sub (subject):主题
      • aud (audience):受众
      • nbf (Not Before):生效时间
      • iat (Issued At):签发时间
      • jti (JWT ID):编号
    • 公开声明(Public Claims):自定义数据字段,如 user_idrole
    • 私有声明(Private Claims):仅供双方约定的字段。
  • 典型结构
    {
      "sub": "1234567890",
      "name": "John Doe",
      "admin": true,
      "iat": 1516239022 // 签发时间
    }
    
  • Base64 编码:经过 Base64 编码后,生成 Payload 部分。
1.3 Signature(签名)
  • 作用:保证 Token 的完整性和不可篡改。
  • 生成方式
    HMACSHA256(
      base64UrlEncode(header) + "." + base64UrlEncode(payload),
      secret
    )
    
    • 使用 Header 和 Payload 的 Base64 编码内容生成签名。Base64URL与Base64算法类似,Base64中+、/和= 在URL中有特殊含义,因此Base64URL 对它们做了处理
    • secret 是服务器端的私钥,仅服务端可知。

JWT 是怎么工作的?

JWT 的工作流程简单,可以分为两步:生成 Token验证 Token

1. 生成 Token
  1. 用户登录时,服务器验证用户名和密码。
  2. 验证通过后,服务器根据用户信息生成 JWT。
  3. 把这个 Token 返回给客户端,客户端存起来(如 localStoragecookie)。
2. 验证 Token
  1. 客户端每次请求时,把 Token 放到 HTTP 请求头里:
   Authorization: Bearer <Token>
  1. 服务器拿到 Token 后,检查:
  • 签名:确认 Token 没被改过。
  • 过期时间:检查 exp 是否有效。
  1. 验证通过后,服务器允许访问资源。

JWT 的优点

  1. 无状态:服务器不用存储会话信息,特别适合分布式系统。
  2. 高效:Token 放在客户端,服务器验证时直接解析,无需查询数据库。
  3. 灵活:可以在 Payload 中添加任何需要的用户信息。

JWT 的缺点

  1. Token 无法主动失效
  • 如果用户登出或权限变更,旧 Token 仍然有效,除非改签名密钥。
  1. Token 体积较大
  • 包含 Header、Payload 和签名,可能会影响网络性能。
  1. JWT默认不加密,在不加密的情况下,不要携带敏感数据
  • JWT 的组成部分(Header、Payload、Signature)是以 Base64 编码存储的,而 Base64 不是加密,只是编码。这意味着任何拿到 JWT 的人都可以轻松解码出 Header 和 Payload,看到里面的内容。

例子:日常生活中的 JWT

假设你去一个游乐园玩,买了一张票(JWT)。

  • 票上的信息(Payload):你的姓名、有效时间、可玩的项目。
  • 防伪标识(Signature):游乐园的官方签名,防止伪造票。

你拿着票(Token)可以自由进入项目(资源)。
如果票到期(过期时间),你需要重新购买(重新登录)。


4. 安全注意事项

  1. 使用 HTTPS
    • 确保 Token 传输过程中不会被窃听。
  2. 设置合理的过期时间
    • 控制 Token 的有效期,减少风险。
  3. 定期更换密钥
    • 避免长期使用同一密钥。
  4. Token 存储位置
    • 避免将 Token 存储在不安全的位置(如 localStorage)。
  5. Token 黑名单
    • 通过数据库记录已失效的 Token 实现黑名单机制,弥补无状态的不足。

5. 实现示例(Go 语言)

依赖安装

使用 github.com/golang-jwt/jwt/v4 包:

go get github.com/golang-jwt/jwt/v4
代码实现
package main

import (
	"fmt"
	"time"

	"github.com/golang-jwt/jwt/v4"
)

var secretKey = []byte("my_secret_key") // 密钥

// 生成 JWT
func GenerateJWT(userID string) (string, error) {
	claims := jwt.MapClaims{
		"user_id": userID,
		"exp":     time.Now().Add(time.Hour * 2).Unix(), // 过期时间
		"iat":     time.Now().Unix(),                   // 签发时间
	}

	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	return token.SignedString(secretKey)
}

// 验证 JWT
func ValidateJWT(tokenString string) (string, error) {
	token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
			return nil, fmt.Errorf("签名方法不匹配")
		}
		return secretKey, nil
	})

	if err != nil {
		return "", err
	}

	if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
		return claims["user_id"].(string), nil
	}

	return "", fmt.Errorf("无效的 Token")
}

func main() {
	// 生成 Token
	token, err := GenerateJWT("12345")
	if err != nil {
		fmt.Println("生成 Token 失败:", err)
		return
	}
	fmt.Println("生成的 Token:", token)

	// 验证 Token
	userID, err := ValidateJWT(token)
	if err != nil {
		fmt.Println("验证 Token 失败:", err)
		return
	}
	fmt.Println("验证成功,用户 ID:", userID)
}

https://github.com/0voice

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值