tydata-server/common/jwt/jwtx_test.go

394 lines
10 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package jwtx
import (
"strings"
"testing"
"time"
"github.com/golang-jwt/jwt/v4"
)
func TestGenerateJwtToken(t *testing.T) {
// 测试数据
testClaims := JwtClaims{
UserId: 1,
AgentId: 0,
Platform: "wxh5",
UserType: 0,
IsAgent: 0,
}
testSecret := "WUvoIwL-FK0qnlxhvxR9tV6SjfOpeJMpKmY2QvT99lA"
testExpire := int64(2592000) // 1小时
tests := []struct {
name string
claims JwtClaims
secret string
expire int64
wantErr bool
}{
{
name: "正常生成token",
claims: testClaims,
secret: testSecret,
expire: testExpire,
wantErr: false,
},
{
name: "不同用户数据",
claims: JwtClaims{
UserId: 99999,
AgentId: 11111,
Platform: "mobile",
UserType: 0,
IsAgent: 1,
},
secret: testSecret,
expire: testExpire,
wantErr: false,
},
{
name: "空密钥",
claims: testClaims,
secret: "",
expire: testExpire,
wantErr: false, // 空密钥不会导致生成失败,但验证时会失败
},
{
name: "零过期时间",
claims: testClaims,
secret: testSecret,
expire: 0,
wantErr: false,
},
{
name: "负数过期时间",
claims: testClaims,
secret: testSecret,
expire: -3600,
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
token, err := GenerateJwtToken(tt.claims, tt.secret, tt.expire)
if (err != nil) != tt.wantErr {
t.Errorf("GenerateJwtToken() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !tt.wantErr {
// 验证token不为空
if token == "" {
t.Error("GenerateJwtToken() 返回的token为空")
return
}
// 验证token格式JWT token应该包含两个点分隔符
parts := strings.Split(token, ".")
if len(parts) != 3 {
t.Errorf("GenerateJwtToken() 返回的token格式不正确期望3部分实际%d部分", len(parts))
return
}
// 验证token可以被解析不验证签名只验证格式
parsedToken, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) {
return []byte(tt.secret), nil
})
if err == nil && parsedToken != nil {
// 验证claims是否正确设置
if claims, ok := parsedToken.Claims.(jwt.MapClaims); ok {
// 验证userId
if userId, exists := claims["userId"]; exists {
if int64(userId.(float64)) != tt.claims.UserId {
t.Errorf("token中的userId不匹配期望%d实际%v", tt.claims.UserId, userId)
}
} else {
t.Error("token中缺少userId字段")
}
// 验证extra字段存在
if _, exists := claims[ExtraKey]; !exists {
t.Error("token中缺少extra字段")
}
// 验证exp字段
if exp, exists := claims["exp"]; exists {
expTime := int64(exp.(float64))
now := time.Now().Unix()
expectedExp := now + tt.expire
// 允许5秒的时间差异
if expTime < expectedExp-5 || expTime > expectedExp+5 {
t.Errorf("token过期时间不正确期望约%d实际%d", expectedExp, expTime)
}
} else {
t.Error("token中缺少exp字段")
}
// 验证iat字段
if _, exists := claims["iat"]; !exists {
t.Error("token中缺少iat字段")
}
}
}
t.Logf("生成的token: %s", token)
}
})
}
}
func TestGenerateJwtTokenAndParse(t *testing.T) {
// 测试生成token后能够正确解析
testClaims := JwtClaims{
UserId: 12345,
AgentId: 67890,
Platform: "web",
UserType: 1,
IsAgent: 0,
}
testSecret := "test-secret-key"
testExpire := int64(3600)
// 生成token
token, err := GenerateJwtToken(testClaims, testSecret, testExpire)
if err != nil {
t.Fatalf("GenerateJwtToken() failed: %v", err)
}
// 解析token
parsedClaims, err := ParseJwtToken(token, testSecret)
if err != nil {
t.Fatalf("ParseJwtToken() failed: %v", err)
}
// 验证解析出的claims与原始claims一致
if parsedClaims.UserId != testClaims.UserId {
t.Errorf("UserId不匹配期望%d实际%d", testClaims.UserId, parsedClaims.UserId)
}
if parsedClaims.AgentId != testClaims.AgentId {
t.Errorf("AgentId不匹配期望%d实际%d", testClaims.AgentId, parsedClaims.AgentId)
}
if parsedClaims.Platform != testClaims.Platform {
t.Errorf("Platform不匹配期望%s实际%s", testClaims.Platform, parsedClaims.Platform)
}
if parsedClaims.UserType != testClaims.UserType {
t.Errorf("UserType不匹配期望%d实际%d", testClaims.UserType, parsedClaims.UserType)
}
if parsedClaims.IsAgent != testClaims.IsAgent {
t.Errorf("IsAgent不匹配期望%d实际%d", testClaims.IsAgent, parsedClaims.IsAgent)
}
t.Logf("测试通过: 生成token并成功解析claims数据一致")
}
func BenchmarkGenerateJwtToken(t *testing.B) {
// 性能测试
testClaims := JwtClaims{
UserId: 12345,
AgentId: 67890,
Platform: "web",
UserType: 1,
IsAgent: 0,
}
testSecret := "test-secret-key"
testExpire := int64(3600)
t.ResetTimer()
for i := 0; i < t.N; i++ {
_, err := GenerateJwtToken(testClaims, testSecret, testExpire)
if err != nil {
t.Fatalf("GenerateJwtToken() failed: %v", err)
}
}
}
func TestParseJwtToken(t *testing.T) {
// 使用你修改的测试数据
testClaims := JwtClaims{
UserId: 6,
AgentId: 0,
Platform: "wxh5",
UserType: 0,
IsAgent: 0,
}
testSecret := "WUvoIwL-FK0qnlxhvxR9tV6SjfOpeJMpKmY2QvT99lA"
testExpire := int64(2592000) // 30天
// 先生成一个token用于测试
token, err := GenerateJwtToken(testClaims, testSecret, testExpire)
if err != nil {
t.Fatalf("生成token失败: %v", err)
}
t.Logf("生成的测试token: %s", token)
tests := []struct {
name string
token string
secret string
wantErr bool
wantClaims *JwtClaims
}{
{
name: "正常解析token",
token: token,
secret: testSecret,
wantErr: false,
wantClaims: &testClaims,
},
{
name: "错误的密钥",
token: token,
secret: "wrong-secret",
wantErr: true,
wantClaims: nil,
},
{
name: "空token",
token: "",
secret: testSecret,
wantErr: true,
wantClaims: nil,
},
{
name: "无效token格式",
token: "invalid.token.format",
secret: testSecret,
wantErr: true,
wantClaims: nil,
},
{
name: "缺少点分隔符的token",
token: "invalidtoken",
secret: testSecret,
wantErr: true,
wantClaims: nil,
},
{
name: "自定义token",
token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3NTI5MDA5MTQsImV4dHJhIjp7ImFnZW50SWQiOjAsImlzQWdlbnQiOjAsInBsYXRmb3JtIjoid3hoNSIsInVzZXJJZCI6NiwidXNlclR5cGUiOjF9LCJpYXQiOjE3NTAzMDg5MTQsInVzZXJJZCI6Nn0.GPKgLOaALOIa1ft7Hipuo4YKFf5guYt0rz2MCDCSdCQ",
secret: testSecret,
wantErr: false,
wantClaims: &testClaims,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
claims, err := ParseJwtToken(tt.token, tt.secret)
if (err != nil) != tt.wantErr {
t.Errorf("ParseJwtToken() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !tt.wantErr && tt.wantClaims != nil {
if claims == nil {
t.Error("ParseJwtToken() 返回的claims为nil")
return
}
// 验证各个字段
if claims.UserId != tt.wantClaims.UserId {
t.Errorf("UserId不匹配期望%d实际%d", tt.wantClaims.UserId, claims.UserId)
}
if claims.AgentId != tt.wantClaims.AgentId {
t.Errorf("AgentId不匹配期望%d实际%d", tt.wantClaims.AgentId, claims.AgentId)
}
if claims.Platform != tt.wantClaims.Platform {
t.Errorf("Platform不匹配期望%s实际%s", tt.wantClaims.Platform, claims.Platform)
}
if claims.UserType != tt.wantClaims.UserType {
t.Errorf("UserType不匹配期望%d实际%d", tt.wantClaims.UserType, claims.UserType)
}
if claims.IsAgent != tt.wantClaims.IsAgent {
t.Errorf("IsAgent不匹配期望%d实际%d", tt.wantClaims.IsAgent, claims.IsAgent)
}
t.Logf("解析成功的claims: UserId=%d, AgentId=%d, Platform=%s, UserType=%d, IsAgent=%d",
claims.UserId, claims.AgentId, claims.Platform, claims.UserType, claims.IsAgent)
}
})
}
}
// TestParseCustomJwtToken 测试解析自定义token - 你可以在这里传入你自己的token
func TestParseCustomJwtToken(t *testing.T) {
// 在这里修改你想要测试的token和secret
customToken := "" // 在这里粘贴你的token
customSecret := "WUvoIwL-FK0qnlxhvxR9tV6SjfOpeJMpKmY2QvT99lA" // 你的密钥
// 如果没有提供自定义token跳过测试
if customToken == "" {
t.Skip("跳过自定义token测试请在代码中设置customToken值")
return
}
t.Logf("解析自定义token: %s", customToken)
claims, err := ParseJwtToken(customToken, customSecret)
if err != nil {
t.Fatalf("解析自定义token失败: %v", err)
}
t.Logf("解析结果:")
t.Logf(" UserId: %d", claims.UserId)
t.Logf(" AgentId: %d", claims.AgentId)
t.Logf(" Platform: %s", claims.Platform)
t.Logf(" UserType: %d", claims.UserType)
t.Logf(" IsAgent: %d", claims.IsAgent)
}
// TestGenerateAndParseWithRealData 生成一个真实的token并解析
func TestGenerateAndParseWithRealData(t *testing.T) {
// 使用真实数据生成token
realClaims := JwtClaims{
UserId: 1,
AgentId: 0,
Platform: "wxh5",
UserType: 0,
IsAgent: 0,
}
realSecret := "WUvoIwL-FK0qnlxhvxR9tV6SjfOpeJMpKmY2QvT99lA"
realExpire := int64(2592000) // 30天
// 生成token
token, err := GenerateJwtToken(realClaims, realSecret, realExpire)
if err != nil {
t.Fatalf("生成token失败: %v", err)
}
t.Logf("=== 生成的完整token ===")
t.Logf("Token: %s", token)
t.Logf("========================")
// 解析token
parsedClaims, err := ParseJwtToken(token, realSecret)
if err != nil {
t.Fatalf("解析token失败: %v", err)
}
t.Logf("=== 解析结果 ===")
t.Logf("UserId: %d", parsedClaims.UserId)
t.Logf("AgentId: %d", parsedClaims.AgentId)
t.Logf("Platform: %s", parsedClaims.Platform)
t.Logf("UserType: %d", parsedClaims.UserType)
t.Logf("IsAgent: %d", parsedClaims.IsAgent)
t.Logf("================")
// 验证数据一致性
if parsedClaims.UserId != realClaims.UserId ||
parsedClaims.AgentId != realClaims.AgentId ||
parsedClaims.Platform != realClaims.Platform ||
parsedClaims.UserType != realClaims.UserType ||
parsedClaims.IsAgent != realClaims.IsAgent {
t.Error("解析出的claims与原始数据不一致")
} else {
t.Log("✅ 数据一致性验证通过")
}
}