jwt_test.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. package auth
  2. import (
  3. "testing"
  4. "time"
  5. "perms-system-server/internal/middleware"
  6. "github.com/golang-jwt/jwt/v4"
  7. "github.com/stretchr/testify/assert"
  8. "github.com/stretchr/testify/require"
  9. )
  10. const testSecret = "test-jwt-secret-key"
  11. // TC-0257: secret="s", expire=3600, userId=1, username="u", productCode="p", memberType="M"
  12. func TestGenerateAccessToken(t *testing.T) {
  13. tests := []struct {
  14. name string
  15. secret string
  16. expire int64
  17. userId int64
  18. username string
  19. productCode string
  20. memberType string
  21. tokenVersion int64
  22. }{
  23. {
  24. name: "normal generation",
  25. secret: testSecret,
  26. expire: 3600,
  27. userId: 1,
  28. username: "admin",
  29. productCode: "p1",
  30. memberType: "ADMIN",
  31. },
  32. {
  33. name: "empty productCode",
  34. secret: testSecret,
  35. expire: 3600,
  36. userId: 3,
  37. username: "user2",
  38. productCode: "",
  39. memberType: "",
  40. },
  41. {
  42. name: "super admin with tokenVersion",
  43. secret: testSecret,
  44. expire: 7200,
  45. userId: 100,
  46. username: "super",
  47. productCode: "p1",
  48. memberType: "SUPER_ADMIN",
  49. tokenVersion: 5,
  50. },
  51. }
  52. for _, tt := range tests {
  53. t.Run(tt.name, func(t *testing.T) {
  54. tokenStr, err := GenerateAccessToken(tt.secret, tt.expire, tt.userId, tt.username, tt.productCode, tt.memberType, tt.tokenVersion)
  55. require.NoError(t, err)
  56. assert.NotEmpty(t, tokenStr)
  57. token, err := jwt.ParseWithClaims(tokenStr, &middleware.Claims{}, func(token *jwt.Token) (interface{}, error) {
  58. return []byte(tt.secret), nil
  59. })
  60. require.NoError(t, err)
  61. assert.True(t, token.Valid)
  62. claims, ok := token.Claims.(*middleware.Claims)
  63. require.True(t, ok)
  64. assert.Equal(t, tt.userId, claims.UserId)
  65. assert.Equal(t, tt.username, claims.Username)
  66. assert.Equal(t, tt.productCode, claims.ProductCode)
  67. assert.Equal(t, tt.memberType, claims.MemberType)
  68. assert.Equal(t, tt.tokenVersion, claims.TokenVersion)
  69. assert.Nil(t, claims.Perms, "Perms should not be embedded in access token (audit #8)")
  70. })
  71. }
  72. }
  73. // TC-0261: expireSeconds=1, sleep 2s
  74. func TestGenerateAccessToken_Expiry(t *testing.T) {
  75. tokenStr, err := GenerateAccessToken(testSecret, 1, 1, "u", "", "", 0)
  76. require.NoError(t, err)
  77. time.Sleep(2 * time.Second)
  78. _, err = jwt.ParseWithClaims(tokenStr, &middleware.Claims{}, func(token *jwt.Token) (interface{}, error) {
  79. return []byte(testSecret), nil
  80. })
  81. assert.Error(t, err)
  82. assert.Contains(t, err.Error(), "token is expired")
  83. }
  84. // TC-0262: secret="s", expire=86400, userId=1, productCode="p"
  85. func TestGenerateRefreshToken(t *testing.T) {
  86. tests := []struct {
  87. name string
  88. secret string
  89. expire int64
  90. userId int64
  91. productCode string
  92. }{
  93. {"normal", testSecret, 86400, 1, "p1"},
  94. {"empty productCode", testSecret, 86400, 2, ""},
  95. }
  96. for _, tt := range tests {
  97. t.Run(tt.name, func(t *testing.T) {
  98. tokenStr, err := GenerateRefreshToken(tt.secret, tt.expire, tt.userId, tt.productCode, 0)
  99. require.NoError(t, err)
  100. assert.NotEmpty(t, tokenStr)
  101. claims, err := ParseRefreshToken(tokenStr, tt.secret)
  102. require.NoError(t, err)
  103. assert.Equal(t, tt.userId, claims.UserId)
  104. assert.Equal(t, tt.productCode, claims.ProductCode)
  105. })
  106. }
  107. }
  108. // TC-0265: 有效token+正确secret
  109. func TestParseRefreshToken(t *testing.T) {
  110. validToken, err := GenerateRefreshToken(testSecret, 3600, 42, "prod", 0)
  111. require.NoError(t, err)
  112. t.Run("valid token", func(t *testing.T) {
  113. claims, err := ParseRefreshToken(validToken, testSecret)
  114. require.NoError(t, err)
  115. assert.Equal(t, int64(42), claims.UserId)
  116. assert.Equal(t, "prod", claims.ProductCode)
  117. })
  118. t.Run("wrong secret", func(t *testing.T) {
  119. _, err := ParseRefreshToken(validToken, "wrong-secret")
  120. assert.Error(t, err)
  121. })
  122. t.Run("invalid token string", func(t *testing.T) {
  123. _, err := ParseRefreshToken("not-a-valid-token", testSecret)
  124. assert.Error(t, err)
  125. })
  126. t.Run("empty token", func(t *testing.T) {
  127. _, err := ParseRefreshToken("", testSecret)
  128. assert.Error(t, err)
  129. })
  130. t.Run("expired token", func(t *testing.T) {
  131. expiredToken, err := GenerateRefreshToken(testSecret, 1, 1, "p", 0)
  132. require.NoError(t, err)
  133. time.Sleep(2 * time.Second)
  134. _, err = ParseRefreshToken(expiredToken, testSecret)
  135. assert.Error(t, err)
  136. })
  137. // TC-0270: AccessToken误用 — TokenType校验拒绝
  138. t.Run("access token used as refresh - should be rejected", func(t *testing.T) {
  139. accessToken, err := GenerateAccessToken(testSecret, 3600, 1, "u", "p", "M", 0)
  140. require.NoError(t, err)
  141. _, err = ParseRefreshToken(accessToken, testSecret)
  142. assert.Error(t, err, "BUG-002: access token 不应被 ParseRefreshToken 接受,应通过 TokenType 字段区分")
  143. })
  144. }
  145. // TC-0259: secret=""
  146. func TestGenerateAccessToken_EmptySecret(t *testing.T) {
  147. tokenStr, err := GenerateAccessToken("", 3600, 1, "u", "p", "M", 0)
  148. require.NoError(t, err)
  149. assert.NotEmpty(t, tokenStr)
  150. token, err := jwt.ParseWithClaims(tokenStr, &middleware.Claims{}, func(token *jwt.Token) (interface{}, error) {
  151. return []byte(""), nil
  152. })
  153. require.NoError(t, err)
  154. assert.True(t, token.Valid)
  155. claims, ok := token.Claims.(*middleware.Claims)
  156. require.True(t, ok)
  157. assert.Equal(t, int64(1), claims.UserId)
  158. }