demo

生成token

type MyClaims struct {
    UserName string `json:"username"`
    UserId   int64  `json:"user_id"`
    jwt.StandardClaims
}

const TokenExpireDuration = time.Hour * 2
var MySecret = []byte("ccuiv")

func GenToken(username string, userID int64) (string, error) {
    // 创建一个自己的声明
    c := MyClaims{
        username,
        userID, // 自定义字段
        jwt.StandardClaims{
            ExpiresAt: time.Now().Add(TokenExpireDuration).Unix(), // 过期时间
            Issuer:    "skyfall",                                  // 签发人
        },
    }
    // 创建签名对象
    token := jwt.NewWithClaims(jwt.SigningMethodHS256, c)
    // 使用指定的secret签名, 并获得完整的,编码后的token
    return token.SignedString(MySecret)
}

解析token

// ParseToken 解析JWT
func ParseToken(tokenString string) (*MyClaims, error) {
    // 解析token
    // 这样直接就是指针,就不用再取地址了
    var mc = new(MyClaims)
    token, err := jwt.ParseWithClaims(tokenString, mc, func(token *jwt.Token) (i interface{}, err error) {
        return MySecret, nil
    })
    if err != nil {
        return nil, err
    }
    if token.Valid { // 校验token
        return mc, nil
    }
    return nil, errors.New("invalid token")
}

gin中注册中间件

// JWTAuthMiddleware 是认证中间件
func JWTAuthMiddleware() func(c *gin.Context) {
    return func(c *gin.Context) {
        // 客户端携带Token有三种方式 1.放在请求头 2.放在请求体 3.放在URl里
        // 这里假设Token放在Header的Authorization中,并使用Bearer开头,再postman测试接口时选用Bearer Token
        // 具体实现方式依据实际情况决定
        authHeader := c.Request.Header.Get("Authorization")
        if authHeader == "" {
            c.JSON(http.StatusOK, gin.H{
                "code": 2003,
                "msg":  "请求头中auth为空",
            })
            c.Abort()
            return
        }
        // 按空格分割
        parts := strings.SplitN(authHeader, " ", 2)
        if !(len(parts) == 2 && parts[0] == "Bearer") {
            c.JSON(http.StatusOK, gin.H{
                "code": 2004,
                "msg":  "请求头中auth格式错误",
            })
            c.Abort()
            return
        }
        // parts[1]用来获取到的tokenString,用之前定义好的解析jwt.ParseToken的函数来解析它
        mc, err := jwt.ParseToken(parts[1])
        if err != nil {
            c.JSON(http.StatusOK, gin.H{
                "code": 2005,
                "msg":  "无效的Token",
            })
            c.Abort()
            return
        }
        // 将当前请求的username信息保存到请求的上下文c上
        c.Set("username", mc.Username)
        c.Next() // 后续的处理函数可以用过c.Get("username")来获取当前请求的用户信息
    }
}

---------------------------*封装后*-----------------------------
---------------------------*封装后*-----------------------------

// JWTAuthMiddleware 基于JWT的认证中间件
func JWTAuthMiddleware() func(c *gin.Context) {
    return func(c *gin.Context) {
        // 客户端携带Token有三种方式 1.放在请求头 2.放在请求体 3.放在URI
        // 这里假设Token放在Header的Authorization中,并使用Bearer开头
        // 具体实现方式依据实际情况决定
        authHeader := c.Request.Header.Get("Authorization")
        if authHeader == "" {
            controlers.ResponseError(c, controlers.CodeNeedLogin)
            c.Abort()
            return
        }
        // 按空格分割
        parts := strings.SplitN(authHeader, " ", 2)
        if !(len(parts) == 2 && parts[0] == "Bearer") {
            controlers.ResponseError(c, controlers.CodeInvalidToken)
            c.Abort()
            return
        }
        // parts[1]是获取到的token,用之前定义好的解析jwt.ParseToken的函数来解析它
        mc, err := jwt.ParseToken(parts[1])
        if err != nil {
            controlers.ResponseError(c, controlers.CodeInvalidToken)
            c.Abort()
            return
        }
        // 将当前请求的userid信息保存到请求的上下文c上
        fmt.Println("----:", mc.UserId)
        // 放在controller层, 避免循环引用
        c.Set(controlers.ContextUserIDKey, mc.UserId)
        c.Next() // 后续的处理函数可以用过c.Get("user_id")来获取当前请求的用户信息
    }
}

install

go get -u github.com/dgrijalva/jwt-go

使用

定义结构体

规定在jwt里存哪些信息

// 定制需求
type MyClaims struct {
    UserName string `json:"username"`
    UserId   int64  `json:"user_id"`
    jwt.StandardClaims
}

定义过期时间

const TokenExpireDuration = time.Hour * 3

定义密钥

var MySecret = []byte("ccuiv")

代码:

type MyClaims struct {
    UserName string `json:"username"`
    UserId   int64  `json:"user_id"`
    jwt.StandardClaims
}

const TokenExpireDuration = time.Hour * 2
var MySecret = []byte("ccuiv")

func GenToken(username string, userID int64) (string, error) {
    // 创建一个自己的声明
    c := MyClaims{
        username,
        userID, // 自定义字段
        jwt.StandardClaims{
            ExpiresAt: time.Now().Add(TokenExpireDuration).Unix(), // 过期时间
            Issuer:    "skyfall",                                  // 签发人
        },
    }
    // 使用指定的签名方法创建签名对象
    token := jwt.NewWithClaims(jwt.SigningMethodHS256, c)
    // 使用指定的secret签名并获得完整的编码后的字符串token
    return token.SignedString(MySecret)
}

解析jwt见demo


在gin中注册中间件见demo

gin中调用demo

r.GET("/ping", middlewares.JWTAuthMiddleware(), func(c *gin.Context) {
    // 如果是登录的用户, 判断请求头中时候有有效的token
    user, _ := controlers.GetCurrentUser(c)
    c.JSON(http.StatusOK, user)
})
分类: go

浙公网安备33011302000604

辽ICP备20003309号