
Go Gin JWT企业级鉴权系统全面实战JWT 是分布式鉴权的首选方案之一。本文把 Gin JWT 全流程讲透从登录、刷新 token、RBAC 到无状态鉴权。一、JWT 基础JWT 由三段组成header.payload.signatureeyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiMTIzNDU2IiwiZXhwIjoxNzMzMDIwMDAwLCJpc3MiOiJteS1zdmMifQ.signatureimportgithub.com/golang-jwt/jwt/v5typeClaimsstruct{UserIDstringjson:user_idjwt.RegisteredClaims}funcGen(userIDstring)(string,error){c:Claims{UserID:userID,RegisteredClaims:jwt.RegisteredClaims{ExpiresAt:jwt.NewNumericDate(time.Now().Add(2*time.Hour)),Issuer:my-svc,},}token:jwt.NewWithClaims(jwt.SigningMethodHS256,c)returntoken.SignedString([]byte(secret))}二、Gin 中间件funcJWTAuth()gin.HandlerFunc{returnfunc(c*gin.Context){tokenStr:c.GetHeader(Authorization)iftokenStr||!strings.HasPrefix(tokenStr,Bearer ){c.AbortWithStatusJSON(401,gin.H{err:missing token})return}tokenStrstrings.TrimPrefix(tokenStr,Bearer )token,_:jwt.ParseWithClaims(tokenStr,Claims{},func(t*jwt.Token)(any,error){return[]byte(secret),nil})claims,ok:token.Claims.(*Claims)if!ok||!token.Valid{c.AbortWithStatusJSON(401,gin.H{err:invalid})return}c.Set(user_id,claims.UserID)c.Next()}}三、Refresh Tokenaccess token短时 15min-2hrefresh token长时 7-30 天。typeRefreshClaimsstruct{UserIDstringjson:user_idjwt.RegisteredClaims}funcGenRefresh(userIDstring)(string,error){c:RefreshClaims{UserID:userID,RegisteredClaims:jwt.RegisteredClaims{ExpiresAt:jwt.NewNumericDate(time.Now().Add(7*24*time.Hour)),},}returnjwt.NewWithClaims(jwt.SigningMethodHS256,c).SignedString([]byte(refresh-secret))}funcRefresh(refreshTokenstring)(string,error){// 验证、签发新 access token}四、RBAC 权限控制typePermClaimsstruct{UserIDstringjson:user_idRoles[]stringjson:rolesPerms[]stringjson:permsjwt.RegisteredClaims}funcRequirePerm(permstring)gin.HandlerFunc{returnfunc(c*gin.Context){v,_:c.Get(claims)claims,_:v.(*PermClaims)for_,p:rangeclaims.Perms{ifpperm{c.Next()return}}c.AbortWithStatusJSON(403,gin.H{err:forbidden})}}r.GET(/api/users,JWTAuth(),RequirePerm(user.read),listUsers)五、JWT 黑名单登出后 token 还会活到过期。加黑名单varblacklistsync.Map{}funcRevoke(tokenIDstring){blacklist.Store(tokenID,true)}funcCheck(tokenIDstring)bool{_,ok:blacklist.Load(tokenID)return!ok}更优雅Redis 存 jtiTTL token 剩余时间。六、生产建议用 64 位 secure random 作为 secret使用 RS256非对称签名而非 HS256token 内不放敏感数据仅 id短 access 长 refresh七、踩坑清单alg‘none’ 攻击必须显式指定签名方法泄露 secret定期换 sign 密钥持久化撤销Redis 黑名单防丢登token 大小影响 HTTP header八、企业实战OAuth2 / OIDC第三方登录可以用 OIDC使用 oidc 库与 IdP 通信。九、总结与展望JWT Gin 让鉴权实现干净。Refresh token 黑名单是当前主流未来结合 Auth0 / casdoor 等 IDaaS 会更省事。未来Passkey FIDO2 进一步强化防钓鱼与无密码登录。十、参考文献JWT RFC 7519golang-jwt 仓库OAuth 2.0 RFC 6749