gin框架中JWT的使用
JWT (JSON Web Token) 是一种规范。这个规范允许我们使用JWT在用户和服务器之间安全传递信息.jwt分3个部分,Header 头部、Payload 载荷、Signature 签名, 用 dot(.) 点分开。想要具体理解jwt的童鞋可以自行百度,这里就不再赘述。
首先我们需要引入jwt库
github.com/dgrijalva/jwt-go
package main
import (
"errors"
"github.com/dgrijalva/jwt-go"
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
"net/http"
"time"
)
const (
ErrorServerBusy = "server is busy"
ErrorReLogin = "relogin"
)
type User struct {
Id int
Name string
}
type JWTClaims struct {
jwt.StandardClaims
User User
}
var (
Secret = "123#111" //salt
ExpireTime = 3600 //token expire time
)
//生成 jwt token
func genToken(user User) (string, error) {
claims := &JWTClaims{
User: user,
}
claims.IssuedAt = time.Now().Unix()
claims.ExpiresAt = time.Now().Add(time.Second * time.Duration(ExpireTime)).Unix()
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
signedToken, err := token.SignedString([]byte(Secret))
if err != nil {
return "", errors.New(ErrorServerBusy)
}
return signedToken, nil
}
//验证jwt token
func verifyToken(ctx *gin.Context) (*JWTClaims, error) {
strToken := ctx.Request.Header.Get("token")
token, err := jwt.ParseWithClaims(strToken, &JWTClaims{}, func(token *jwt.Token) (interface{}, error) {
return []byte(Secret), nil
})
if err != nil {
return nil, errors.New(ErrorServerBusy)
}
claims, ok := token.Claims.(*JWTClaims)
if !ok {
return nil, errors.New(ErrorReLogin)
}
if err := token.Claims.Valid(); err != nil {
return nil, errors.New(ErrorReLogin)
}
return claims, nil
}
// 更新token
func refresh(c *gin.Context) (string, error) {
claims, _ := verifyToken(c)
return genToken(claims.User)
}
func jwtAuth(ctx *gin.Context) {
if _, err := verifyToken(ctx); err == nil {
ctx.Next()
} else {
ctx.JSON(http.StatusOK, gin.H{"code": 4001})
ctx.Abort()
}
}
func main() {
router := gin.Default()
//在web开发中,浏览器处于安全考虑会限制跨域请求。
//我们采用前后端分离的方式写接口的时候服务器端要允许跨域请求
//使用 cors中间件 允许跨域
router.Use(cors.Default())
router.GET("/login", func(ctx *gin.Context) {
user := User{1, "hanyun"}
singedToken, err := genToken(user)
if err == nil {
ctx.JSON(http.StatusOK, gin.H{"code": 0, "token": singedToken})
} else {
ctx.JSON(http.StatusOK, gin.H{"code": 1, "token": singedToken})
}
})
//使用自定义的jwtAuth中间件
router.Use(jwtAuth)
router.GET("/user", func(context *gin.Context) {
claims, _ := verifyToken(context)
context.JSON(http.StatusOK, gin.H{"code": 0, "user": claims.User})
})
router.GET("/refresh", func(context *gin.Context) {
singedToken, err:= refresh(context)
if err == nil {
context.JSON(http.StatusOK, gin.H{"code": 0, "token": singedToken})
} else {
context.JSON(http.StatusOK, gin.H{"code": 1, "token": singedToken})
}
})
router.Run()
}
1、我们访问http://127.0.0.1:8080/login,获得token,结果如下
{
"code": 0,
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODM2NzQ2MzEsImlhdCI6MTU4MzY3MTAzMSwiVXNlciI6eyJJZCI6MSwiTmFtZSI6Imhhbnl1biJ9fQ.kMmE3DWXvNOUVsuHWgrlbm2pbsOHmbMtyr-V6hVjQ4s"
}
2、访问http://127.0.0.1:8080/user,同时在header里面加入token,获得用户信息
postman示例如下

curl示例如下
curl --location --request GET 'http://127.0.0.1:8080/user' \
--header 'token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODM2NzQ2MzEsImlhdCI6MTU4MzY3MTAzMSwiVXNlciI6eyJJZCI6MSwiTmFtZSI6Imhhbnl1biJ9fQ.kMmE3DWXvNOUVsuHWgrlbm2pbsOHmbMtyr-V6hVjQ4s'
结果如下
{
"code": 0,
"user": {
"Id": 1,
"Name": "hanyun"
}
}
3、刷新token,访问http://127.0.0.1:8080/refresh
postman示例如下

curl请求示例如下
curl --location --request GET 'http://127.0.0.1:8080/refresh' \
--header 'token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODM2NzQ2MzEsImlhdCI6MTU4MzY3MTAzMSwiVXNlciI6eyJJZCI6MSwiTmFtZSI6Imhhbnl1biJ9fQ.kMmE3DWXvNOUVsuHWgrlbm2pbsOHmbMtyr-V6hVjQ4s'

记着关注我哦
