JWT Token刷新实战:Go语言版
创作时间:
作者:
@小白创作中心
JWT Token刷新实战:Go语言版
引用
CSDN
等
6
来源
1.
https://blog.csdn.net/Gaorui678/article/details/139030661
2.
https://blog.csdn.net/weixin_44102152/article/details/138667173
3.
https://blog.csdn.net/hzb869168467/article/details/136310155
4.
https://www.cnblogs.com/XY-Heruo/p/18280787
5.
https://www.cnblogs.com/QiaoPengjun/p/18630890
6.
https://www.cnblogs.com/failymao/p/18059012
在现代Web应用开发中,JWT(JSON Web Tokens)已经成为主流的认证解决方案。然而,JWT Token的过期问题一直是开发者需要解决的重要课题。本文将通过Go语言及其流行的Gin框架,详细讲解如何高效可靠地实现JWT Token刷新功能。
JWT Token刷新原理
在JWT认证体系中,通常会使用两种Token:Access Token和Refresh Token。
- Access Token:用于访问受保护资源的凭据,有效期较短(如15分钟),以提高安全性。
- Refresh Token:用于在Access Token过期后获取新的Access Token,有效期较长,有时甚至是永久有效的。
刷新流程如下:
- 用户初次登录时,服务器返回Access Token和Refresh Token。
- 客户端在每次请求时携带Access Token。
- 当Access Token过期时,客户端使用Refresh Token请求新的Access Token。
- 服务器验证Refresh Token有效后,返回新的Access Token。
- 如果Refresh Token也过期或无效,用户需要重新登录。
Go语言实现JWT Token刷新
环境准备
首先,确保已经安装了必要的Go包:
go get -u github.com/gin-gonic/gin
go get -u github.com/golang-jwt/jwt/v5
代码实现
- 定义JWT相关结构体
package main
import (
"github.com/golang-jwt/jwt/v5"
"time"
)
// JWTClaims 包含用户ID和过期时间
type JWTClaims struct {
UserID uint `json:"user_id"`
jwt.RegisteredClaims
}
// JWTSecret 签名密钥
var JWTSecret = []byte("your-secret-key")
- 生成JWT Token
func GenerateToken(userID uint) (string, error) {
claims := JWTClaims{
UserID: userID,
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(15 * time.Minute)),
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString(JWTSecret)
}
- 刷新JWT Token
func RefreshToken(oldToken string) (string, error) {
token, err := jwt.ParseWithClaims(oldToken, &JWTClaims{}, func(token *jwt.Token) (interface{}, error) {
return JWTSecret, nil
})
if err != nil {
return "", err
}
if claims, ok := token.Claims.(*JWTClaims); ok && token.Valid {
newClaims := JWTClaims{
UserID: claims.UserID,
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(15 * time.Minute)),
},
}
newToken := jwt.NewWithClaims(jwt.SigningMethodHS256, newClaims)
return newToken.SignedString(JWTSecret)
}
return "", errors.New("invalid token")
}
- Gin 路由配置
func main() {
r := gin.Default()
// 公开接口:登录
r.POST("/login", func(c *gin.Context) {
// 这里应该包含验证用户名和密码的逻辑
// 假设验证通过,生成Token
token, err := GenerateToken(1) // 假设用户ID为1
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"token": token})
})
// 受保护接口:需要JWT认证
protected := r.Group("/api")
protected.Use(AuthMiddleware())
{
protected.GET("/user", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"message": "Welcome!"})
})
}
// Token刷新接口
r.POST("/refresh_token", func(c *gin.Context) {
var req struct {
Token string `json:"token" binding:"required"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
newToken, err := RefreshToken(req.Token)
if err != nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid token"})
return
}
c.JSON(http.StatusOK, gin.H{"token": newToken})
})
r.Run(":8080")
}
- JWT认证中间件
func AuthMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
tokenString := c.GetHeader("Authorization")
if tokenString == "" {
c.AbortWithStatus(http.StatusUnauthorized)
return
}
token, err := jwt.ParseWithClaims(tokenString, &JWTClaims{}, func(token *jwt.Token) (interface{}, error) {
return JWTSecret, nil
})
if err != nil || !token.Valid {
c.AbortWithStatus(http.StatusUnauthorized)
return
}
claims, ok := token.Claims.(*JWTClaims)
if !ok {
c.AbortWithStatus(http.StatusUnauthorized)
return
}
c.Set("user_id", claims.UserID)
c.Next()
}
}
安全考虑
- 保护Refresh Token:由于Refresh Token具有长期有效性,应妥善存储,避免在前端存储,建议存储在服务器端或使用HTTP-only Cookies。
- 传输安全:所有涉及Token的请求都应通过HTTPS进行,防止中间人攻击。
- 限制刷新次数:可以设置Refresh Token的使用次数限制,进一步增强安全性。
- 定期更新Refresh Token:即使Refresh Token有效期较长,也应定期更新,避免长期固定不变。
通过以上实现,我们可以在Go语言中高效地处理JWT Token的刷新逻辑,既保证了用户认证的安全性,又提升了用户体验。希望这些代码示例能帮助你更好地理解和实现JWT Token刷新功能。
热门推荐
欧洲史:阿拉伯与丕平三世的币制改革提供借鉴经验是什么?
合同到期续签降薪合法吗?一文详解劳动合同续签中的权益保护
期货中的EMA是什么意思?这种指标对交易决策有何帮助?
巴西的“G20时刻”:地区大国的全球雄心与地缘政治掣肘
碱性矿泉水真的能活化细胞吗
如何规划家庭财务以应对房价波动?这些规划有哪些实际效果?
NAT基本原理及穿透详解(打洞)
四人斗地主:地主与农民的玩法攻略
拖欠工资不给怎么处理最有效的方法
KDJ指标的准确设置方法是什么?这种设置方法的实际效果如何?
制造业中的“大数据”:如何实现精准决策?
电瓶内阻大应如何解决?解决该问题后怎样确保电瓶的正常使用?
如何检查润滑油的质量是否合格(附润滑油的换油标准)
儿童支原体肺炎卷土重来,如何应对?
等级保护政策、流程、内容、定级介绍
仓储合同应具备的关键条款
能源行业近期人事变动
马士英:以身殉国的“奸臣”之谜
五行能量补给站:解锁你的活力密码
海水为什么不能喝?神秘的海水烧干后会得到什么?
用ChatGPT做课题申报,看着一篇就够了(附详细指令)
如何在办公室进行合理布局?这些设计有哪些工作效率的提升?
C语言如何防止头文件重复调用
劳务合同费用约定:定义、原则与法律效力详解
徐州十大必吃美食,从地锅鸡到蛙鱼,你尝过几个?
借阅排行屡上榜 金庸江湖未退潮
古代的沙发叫什么?了解传统家具魅力
广州地铁新宠:23号线强势来袭,畅行四区,规划线路全长45.1公里
缓解牙痛的最佳方法与预防技巧分享
如何看待油价过高的现象?这种现象对汽车行业有何影响?