一、在gin
中使用jwt-go
来生成token
-
1、安装包
go get -u github.com/dgrijalva/jwt-go 复制代码
-
2、定义基础的结构体
// 签名需要传递的参数 type HmacUser struct { Id string `json:"id"` Username string `json:"username"` } type MyClaims struct { UserId string `json:"user_id"` Username string `json:"username"` jwt.StandardClaims } // 登录的参数 type LoginStruct struct { Username string `json:"username"` Password string `json:"password"` } // 证书签名密钥 var jwtKey = []byte("abc") 复制代码
-
3、定义生成
token
的方法// 定义生成token的方法 func generateToken(u HmacUser) (string, error) { // 定义过期时间,7天后过期 expirationTime := time.Now().Add(7 * 24 * time.Hour) claims := &MyClaims{ UserId: u.Id, Username: u.Username, StandardClaims: jwt.StandardClaims{ ExpiresAt: expirationTime.Unix(), // 过期时间 IssuedAt: time.Now().Unix(), // 发布时间 Subject: "token", // 主题 Issuer: "水痕", // 发布者 }, } // 注意单词别写错了 token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) tokenString, err := token.SignedString(jwtKey) if err != nil { return "", err } return tokenString, nil } 复制代码
-
4、定义一个路由来生成
token
router := gin.Default() router.POST("/login", func(c *gin.Context) { var loginStruct LoginStruct err := c.BindJSON(&loginStruct) if err != nil { fmt.Println("解析数据错误") c.JSON(http.StatusOK, gin.H{ "code": 1, "message": "解析数据错误", }) return } // 这里就不做查表操作验证用户名和密码 fmt.Println("登录参数", loginStruct) // 传递给生成token的方法中 userInfo := HmacUser{ Id: "1", Username: loginStruct.Username, } token, err := generateToken(userInfo) if err != nil { fmt.Println(err, "===") c.JSON(http.StatusOK, gin.H{ "code": 1, "message": "生成token失败", }) return } c.JSON(http.StatusOK, gin.H{ "code": 0, "message": "登录成功", "token": token, }) }) 复制代码
二、使用中间件来验证客户端传递过来的token
-
1、解析
token
// 定义解析token的方法 func parseToken(tokenString string) (*jwt.Token, *MyClaims, error) { claims := &MyClaims{} token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) { return jwtKey, nil }) return token, claims, err } 复制代码
-
2、在中间件中验证
token
// 定义中间件 func AuthMiddleware() gin.HandlerFunc { return func(c *gin.Context) { // 从请求头中获取token tokeString := c.GetHeader("token") fmt.Println(tokeString, "当前token") if tokeString == "" { c.JSON(http.StatusOK, gin.H{ "code": 1, "message": "必须传递token", }) c.Abort() return } token, claims, err := parseToken(tokeString) if err != nil || !token.Valid { c.JSON(http.StatusOK, gin.H{ "code": 1, "message": "token解析错误", }) c.Abort() return } // 从token中解析出来的数据挂载到上下文上,方便后面的控制器使用 c.Set("userId", claims.UserId) c.Set("userName", claims.Username) c.Next() } } 复制代码
-
3、定义路由使用中间件
// 使用中间件 router.POST("/check_token", AuthMiddleware(), func(c *gin.Context) { if userName, exists := c.Get("userName"); exists { fmt.Println("当前用户", userName) } c.JSON(http.StatusOK, gin.H{ "code": 0, "message": "验证成功", }) }) 复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END