狗林技术

  • 首页
  • 技术分享
    • PHP
    • Go
    • Linux
    • JavaScript
    • Vue
    • 其他

Menu

  • 首页
  • 技术分享
    • PHP
    • Go
    • Linux
    • JavaScript
    • Vue
    • 其他
  • 1970.01.01遇到Undefined constant "CURL_SSLVERSION_TLSv1_2"错误
  • 1970.01.01linux防火墙操作
  • 1970.01.01linux centos系统安装php的redis扩展
  • 1970.01.01Golang实现自定义JWT生成与验证
  • 1970.01.01php项目中Nginx文件解析漏洞
  • 1970.01.01Nginx配置跨域
更多
个人简介
个人简介


职业:PHP开发,Go开发

          前端开发

现居:浙江省-杭州市

Email:1047571953@qq.com

                               

热门文章

  • git的学习过程

    git的一些常用命令

  • Go文档

    Go http://www.topgoer.com gorm https://learnku.com/docs/gorm/v2/about-mirror-image/9754 gin https://www.kancloud.cn/lhj0702/sockstack_gin/1805355

  • tp5.1用GatewayWorker做一个简单的聊天室

    tp5.1用GatewayWorker做一个简单的聊天室 , 源码文件

  • TP5.1 查询数据库中上一条和下一条记录

    ->where("id", ">", $id)->order("id", "asc")->find();<br/> ​->where('id' , '<' , $id)->order("id", "desc")->find();

联系我

    zxl77l 微信号 1047571953@qq.com QQ邮箱 1047571953 QQ号

Golang实现自定义JWT生成与验证

分类:Go   作者:   - 发布于:2024/07/09   1226

需要用到的包

import (
    "errors"
    "gin_web/app/models/admin"
    "gin_web/config"

    "github.com/dgrijalva/jwt-go"
)

首先自定义结构体并继承jwt.StandardClaims

// Claims 自定义声明结构体并内嵌jwt.StandardClaims
type CustomClaims struct {
    UserID uint64 `json:"user_id"`
    jwt.StandardClaims
}

func NewCustomClaims(userID uint64) CustomClaims {
    return CustomClaims{
        userID,
        jwt.StandardClaims{
            ExpiresAt: config.Jwt.ExpiresAt,
            Issuer:    config.Jwt.Issuer,
        },
    }
}

生成jwt与验证的方法

// GenerateToken 生成JWT
func GenerateToken(claims jwt.Claims) (string, error) {
    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    // 生成签名字符串
    tokenStr, err := token.SignedString([]byte(config.Jwt.SecretKey))
    if err != nil {
        return "", err
    }
    return tokenStr, nil
}

// ParseToken 解析JWT
func ParseToken(tokenString string, claims jwt.Claims) error {
    token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
        return []byte(config.Jwt.SecretKey), nil
    })
    if err != nil {
        return err
    }
    // 对token对象中的Claim进行类型断言
    if token.Valid { // 校验token
        return nil
    }
    return errors.New("invalid token")
}


整体代码

package jwtutils

import (
    "errors"
    "gin_web/app/models/admin"
    "gin_web/config"

    "github.com/dgrijalva/jwt-go"
)

// Claims 自定义声明结构体并内嵌jwt.StandardClaims
type CustomClaims struct {
    UserID uint64 `json:"user_id"`
    jwt.StandardClaims
}

func NewCustomClaims(userID uint64) CustomClaims {
    return CustomClaims{
        userID,
        jwt.StandardClaims{
            ExpiresAt: config.Jwt.ExpiresAt,
            Issuer:    config.Jwt.Issuer,
        },
    }
}

// GenerateToken 生成JWT
func GenerateToken(claims jwt.Claims) (string, error) {
    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    // 生成签名字符串
    tokenStr, err := token.SignedString([]byte(config.Jwt.SecretKey))
    if err != nil {
        return "", err
    }
    return tokenStr, nil
}

// ParseToken 解析JWT
func ParseToken(tokenString string, claims jwt.Claims) error {
    token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
        return []byte(config.Jwt.SecretKey), nil
    })
    if err != nil {
        return err
    }
    // 对token对象中的Claim进行类型断言
    if token.Valid { // 校验token
        return nil
    }
    return errors.New("invalid token")
}


声明后台结构体自定义内容格式,并使用

jwtutils包中定义如下代码

// AdminCustomClaims 自定义格式内容
type AdminCustomClaims struct {
    AdminInfo          *admin.AdminModel
    jwt.StandardClaims // 内嵌标准的声明
}

// NewAdminCustomClaims 初始化AdminCustomClaims
func NewAdminCustomClaims(userInfo *admin.AdminModel, expiresAt int64) AdminCustomClaims {
    return AdminCustomClaims{
        userInfo,
        jwt.StandardClaims{
            ExpiresAt: expiresAt,
            Issuer:    config.Jwt.Issuer,
        },
    }
}

login方法中使用

adminUserInfo, err := adminUserModel.FirstByUsername(params.UserName)
    //验证密码
    if err != nil || !utils.PasswordVerify(params.PassWord, adminUserInfo.Password) {
        response.Error(ctx, "用户不存在或密码错误!", nil)
        return
    }
    //生成token
    claims := jwtutils.NewAdminCustomClaims(adminUserInfo, time.Now().Add(time.Hour*72).Unix())
    tokenString, err := jwtutils.GenerateToken(claims)
    if err != nil {
        response.Error(ctx, "登录失败,Token生成失败!"+err.Error(), nil)
        return
    }
    go func() {
        //验证通过,更新登陆时间和ip,记录Session
        adminUserModel.Update(adminUserInfo.AdminId, map[string]interface{}{
            "last_login_ip":   ctx.ClientIP(),
            "last_login_time": time.Now().Format("2006-01-02 15:04:05"),
        })
    }()

    response.Success(ctx, "登陆成功!", gin.H{
        "token":    tokenString,
        "nickname": adminUserInfo.Username,
        "avatar":   adminUserInfo.Avatar,
    })

中间件验证token

package middleware

import (
    "errors"
    "gin_web/app/response"
    "gin_web/app/utils/jwtutils"
    "net/http"
    "strings"

    "github.com/dgrijalva/jwt-go"
    "github.com/gin-gonic/gin"
)

// AdminAuthHandler后台认证
func AdminAuthHandler() gin.HandlerFunc {
    return func(c *gin.Context) {
        // 从请求头中获取 Authorization 字段
        authHeader := c.GetHeader("Authorization")
        if authHeader == "" {
            response.AbortWithStatusJSON(c, http.StatusUnauthorized, "Unauthorized", nil, http.StatusAccepted)
            return
        }
        // 检查Bearer Token格式
        parts := strings.Split(authHeader, " ")
        if len(parts) != 2 || parts[0] != "Bearer" {
            response.AbortWithStatusJSON(c, http.StatusUnauthorized, "The token format is incorrect", nil, http.StatusAccepted)
            return
        }
        // 验证Token
        tokenStr := parts[1]
        adminCustomClaims := &jwtutils.AdminCustomClaims{}
        if err := jwtutils.ParseToken(tokenStr, adminCustomClaims); err != nil {
            if errors.Is(err, jwt.ErrSignatureInvalid) {
                response.AbortWithStatusJSON(c, http.StatusUnauthorized, "Token verification failed", nil, http.StatusAccepted)
            } else {
                response.AbortWithStatusJSON(c, http.StatusUnauthorized, "Bad Request", nil, http.StatusAccepted)
            }
            return
        }
        // 将解析后的 claims 附加到上下文中,以便后续处理器使用
        c.Set("adminId", adminCustomClaims.AdminInfo.AdminId)
        c.Set("username", adminCustomClaims.AdminInfo.Username)
        c.Set("roleId", adminCustomClaims.AdminInfo.RoleId)
        c.Set("adminInfo", adminCustomClaims.AdminInfo)

        c.Next()
    }
}


上一篇 : 没有上一篇了哦!

下一篇 : Go文档

-------------本文结束感谢您的阅读-------------

首页 技术分享

湘ICP备2021006798号

Copyright © 2021 狗林技术. All Rights Reserved.

友情链接: 测试链接

大家都在搜

  • 张三
  • 李四
  • 王二

关注我

微信号