ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Gin-JWT认证与授权方案从Token到RBAC权限控制

Gin-JWT认证与授权方案从Token到RBAC权限控制 Gin-JWT认证与授权方案从Token到RBAC权限控制文章导语JWTJSON Web Token是现代Web服务的身份认证标准。在Gin框架中集成JWT看似简单但涉及Token刷新、黑名单、多设备登录、RBAC权限控制等实际需求时就需要更完善的设计。本文将从基础到进阶构建一个生产级的Gin JWT认证授权系统。一、JWT基础实现importgithub.com/golang-jwt/jwt/v5// 自定义ClaimstypeCustomClaimsstruct{UserIDuintjson:user_idUsernamestringjson:usernameRolestringjson:rolejwt.RegisteredClaims}// 生成TokenfuncGenerateToken(userIDuint,usernamestring,rolestring,secret[]byte)(string,error){claims:CustomClaims{UserID:userID,Username:username,Role:role,RegisteredClaims:jwt.RegisteredClaims{ExpiresAt:jwt.NewNumericDate(time.Now().Add(24*time.Hour)),IssuedAt:jwt.NewNumericDate(time.Now()),Issuer:myapp,Subject:fmt.Sprintf(%d,userID),},}token:jwt.NewWithClaims(jwt.SigningMethodHS256,claims)returntoken.SignedString(secret)}// 解析TokenfuncParseToken(tokenStringstring,secret[]byte)(*CustomClaims,error){token,err:jwt.ParseWithClaims(tokenString,CustomClaims{},func(token*jwt.Token)(interface{},error){if_,ok:token.Method.(*jwt.SigningMethodHMAC);!ok{returnnil,fmt.Errorf(unexpected signing method: %v,token.Header[alg])}returnsecret,nil})iferr!nil{returnnil,err}ifclaims,ok:token.Claims.(*CustomClaims);oktoken.Valid{returnclaims,nil}returnnil,errors.New(invalid token)}二、Gin中间件集成funcAuthMiddleware(secret[]byte)gin.HandlerFunc{returnfunc(c*gin.Context){// 从Header获取TokenauthHeader:c.GetHeader(Authorization)ifauthHeader{c.AbortWithStatusJSON(401,gin.H{msg:请提供认证令牌})return}// Bearer Token格式parts:strings.SplitN(authHeader, ,2)iflen(parts)!2||parts[0]!Bearer{c.AbortWithStatusJSON(401,gin.H{msg:认证格式错误})return}claims,err:ParseToken(parts[1],secret)iferr!nil{c.AbortWithStatusJSON(401,gin.H{msg:令牌无效或已过期})return}// 将用户信息存入Contextc.Set(user_id,claims.UserID)c.Set(username,claims.Username)c.Set(role,claims.Role)c.Next()}}三、Token刷新机制// 双Token策略Access Token Refresh TokenfuncRefreshToken(c*gin.Context){varreqstruct{RefreshTokenstringjson:refresh_token binding:required}iferr:c.ShouldBindJSON(req);err!nil{c.JSON(400,gin.H{msg:参数错误})return}// 验证Refresh Tokenclaims,err:ParseToken(req.RefreshToken,refreshSecret)iferr!nil{c.JSON(401,gin.H{msg:Refresh Token无效})return}// 检查Refresh Token是否在黑名单ifisBlacklisted(claims.ID){c.JSON(401,gin.H{msg:Refresh Token已被撤销})return}// 生成新的Access TokennewToken,err:GenerateToken(claims.UserID,claims.Username,claims.Role,accessSecret)iferr!nil{c.JSON(500,gin.H{msg:生成Token失败})return}c.JSON(200,gin.H{access_token:newToken,expires_in:86400,})}四、RBAC权限控制// 权限常量const(RoleAdminadminRoleUseruser)// 权限中间件funcRequireRole(roles...string)gin.HandlerFunc{returnfunc(c*gin.Context){userRole,exists:c.Get(role)if!exists{c.AbortWithStatusJSON(403,gin.H{msg:权限不足})return}for_,role:rangeroles{ifuserRole.(string)role{c.Next()return}}c.AbortWithStatusJSON(403,gin.H{msg:权限不足})}}// 使用router:gin.Default()router.Use(AuthMiddleware(secret))adminGroup:router.Group(/admin)adminGroup.Use(RequireRole(RoleAdmin)){adminGroup.GET(/dashboard,adminDashboard)adminGroup.DELETE(/users/:id,adminDeleteUser)}userGroup:router.Group(/user)userGroup.Use(RequireRole(RoleUser,RoleAdmin)){userGroup.GET(/profile,userProfile)}五、Token黑名单Redis实现funcLogout(c*gin.Context){tokenString:extractToken(c)claims,_:ParseToken(tokenString,secret)// 将Token加入黑名单expiration:time.Until(claims.ExpiresAt.Time)err:rdb.Set(ctx,blacklist:claims.ID,1,expiration).Err()iferr!nil{c.JSON(500,gin.H{msg:登出失败})return}c.JSON(200,gin.H{msg:登出成功})}funcisBlacklisted(tokenIDstring)bool{exists,_:rdb.Exists(ctx,blacklist:tokenID).Result()returnexists0}六、全文总结JWT Gin中间件实现无状态认证双Token策略解决Token过期刷新问题RBAC中间件实现细粒度权限控制Redis黑名单实现Token主动失效验证签名算法防伪造七、技术进阶展望OAuth2.0与Gin的集成SSO单点登录在Go中的实现JWT的Ed25519签名算法参考文献JWT RFC 7519: https://tools.ietf.org/html/rfc7519golang-jwt: https://github.com/golang-jwt/jwtGin中间件文档Auth0 - JWT Best PracticesOWASP - Authentication Cheat Sheet
返回列表