Gin通过jwt方式实现登录验证基本示例
程序开发
2023-09-03 23:24:57
本文使用Go Gin框架搭建的webserver示例,其中使用jwt进行登录验证,至于cookies session jwt token的区别,优缺点不再本位讨论范围内。
简单总结:使用jwt更方便,具有一定程度安全性,
具体使用Gin搭建webserver提供API服务部分就不赘述了, 可以参考其他博客介绍。完整代码在这里,
代码结构
1 定义jwt格式部分所需信息和Gin middleware
在标准的Claims信息之外添加一些自定义信息
// 载荷,可添加自己需要的一些信息
type CustomClaims struct {UserId int64 `json:"userId"`UserName string `json:"userName"`RoleId string `json:"roleId"`jwt.StandardClaims
}
类似于java中过滤器
func JWTAuth() gin.HandlerFunc {return func(c *gin.Context) {//过滤是否验证token, login结构直接放行,这里为了简单起见,直接判断路径中是否带login,携带login直接放行if strings.Contains(c.Request.RequestURI, "login") {return}token := c.Request.Header.Get("token")if token == "" {c.JSON(http.StatusOK, gin.H{"status": -1,"msg": "请求未携带token,无权限访问",})c.Abort()return}klog.Infof("gotten token:%s", token)j := NewJWT()// parse token, get the user and role infoclaims, err := j.ParseToken(token)if err != nil {if err == util.TokenExpired {c.JSON(http.StatusOK, gin.H{"status": -1,"msg": "授权已过期",})c.Abort()return}c.JSON(http.StatusOK, gin.H{"status": -1,"msg": err.Error(),})c.Abort()return}// 继续交由下一个路由处理,并将解析出的信息传递下去c.Set(util.Gin_Context_Key, claims)}
}
2 配置路由
/login接口不需要验证登录, 其他接口需要验证登录的token
func ConfigRouter(router *gin.Engine) {userController := mycontroller.NewUserController()//配置middlewarerouter.Use(myjwt.JWTAuth())router.POST("/login", userController.Login)router.GET("/users", userController.GetAllUsers)router.GET("/usersfind", userController.FindUsers)router.GET("/users/:userId", userController.GetOneUser)router.PUT("/users", userController.CreateOneUser)router.POST("/users/:userId", userController.UpdateOneUser)router.DELETE("/users/:userId", userController.DeleteOneUser)
}
3 生成与解析token
生成token
func generateToken(c *gin.Context, user mydomain.User, roleId string, expiredTimeByMinute int64) {j := &myjwt.JWT{[]byte(util.SignKey),}claims := myjwt.CustomClaims{user.UserId,user.UserName,roleId,jwtgo.StandardClaims{NotBefore: int64(time.Now().Unix() - 1000), // 签名生效时间ExpiresAt: int64(time.Now().Unix() + expiredTimeByMinute*60), // 过期时间 一小时Issuer: "ginjwtdemo", //签名的发行者},}token, err := j.CreateToken(claims)if err != nil {c.JSON(http.StatusOK, gin.H{"status": -1,"msg": err.Error(),})return}data := mydomain.LoginResp{Token: token,}c.JSON(http.StatusOK, gin.H{"status": 0,"msg": "登录成功!","data": data,})return
}
解析token
func (j *JWT) ParseToken(tokenString string) (*CustomClaims, error) {token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) {return j.SigningKey, nil})if err != nil {if ve, ok := err.(*jwt.ValidationError); ok {if ve.Errors&jwt.ValidationErrorMalformed != 0 {return nil, util.TokenMalformed} else if ve.Errors&jwt.ValidationErrorExpired != 0 {// Token is expiredreturn nil, util.TokenExpired} else if ve.Errors&jwt.ValidationErrorNotValidYet != 0 {return nil, util.TokenNotValidYet} else {return nil, util.TokenInvalid}}}if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid {return claims, nil}return nil, util.TokenInvalid
}
4 效果演示
获取token
在header中添加一个过期api的效果
在header中没有token访问api的效果
在header中添加一个当前有效的token访问api的效果
标签:
上一篇:
html浏览器内核及兼容性
下一篇:
相关文章
-
无相关信息