gin 基于JWT实现token令牌功能

简介: token 我的理解是一种凭证,客户端请求时携带此凭证才能有效访问需要验证凭证的服务端接口,而且token可以加密携带客户端的一些信息,比如基本的信息是有效期,生效日期,可以看作是令牌。

token 我的理解是一种凭证,客户端请求时携带此凭证才能有效访问需要验证凭证的服务端接口,而且token可以加密携带客户端的一些信息,比如基本的信息是有效期,生效日期,可以看作是令牌。加密后是一串字符串

基于JWT的Token认证机制实现

JSON Web Token(JWT)是一个非常轻巧的规范。这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息。

JWT的组成

一个JWT实际上就是一个字符串,它由三部分组成,头部、载荷与签名。

例子

jwt.go 负责token生成,验证

package jwt

import (
    "github.com/gin-gonic/gin"
    "github.com/dgrijalva/jwt-go"
    "errors"
    "time"
    "net/http"
    "log"
)
// 中间件,检查token
func JWTAuth() gin.HandlerFunc {
    return func(c *gin.Context) {
        token :=  c.Request.Header.Get("token")
        if token == ""{
            c.JSON(http.StatusOK,gin.H{
                "status":-1,
                "msg":"请求未携带token,无权限访问",
            })
            c.Set("isPass", false)
            return
        }

        log.Print("get token: ",token)

        j := NewJWT()
        // parseToken
        claims, err := j.ParseToken(token)
        if err != nil {
            if err == TokenExpired {
                c.JSON(http.StatusOK,gin.H{
                    "status":-1,
                    "msg":"授权已过期",
                })
                c.Set("isPass", false)
                return
            }
            c.JSON(http.StatusOK, gin.H{
                "status": -1,
                "msg": err.Error(),
                })
            c.Set("isPass", false)
            return
        }
        c.Set("isPass", true)
        c.Set("claims",claims)
    }
}
// 签名
type JWT struct {
    SigningKey []byte
}

var (
    TokenExpired error = errors.New("Token is expired")
    TokenNotValidYet error = errors.New("Token not active yet")
    TokenMalformed error = errors.New("That's not even a token")
    TokenInvalid error = errors.New("Couldn't handle this token:")
    SignKey string = "newtrekWang"
)
// 载荷
type CustomClaims struct {
    ID string `json:"userId"`
    Name string `json:"name"`
    Phone string `json:"phone"`
    jwt.StandardClaims
}
func NewJWT() *JWT {
    return &JWT{
        []byte(GetSignKey()),
    }
}
func GetSignKey() string {
    return SignKey
}
func SetSignKey(key string) string {
    SignKey = key
    return SignKey
}


func (j *JWT) CreateToken(claims CustomClaims) (string, error) {
    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    return token.SignedString(j.SigningKey)
}

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, TokenMalformed
            } else if ve.Errors&jwt.ValidationErrorExpired != 0 {
                // Token is expired
                return nil, TokenExpired
            } else if ve.Errors&jwt.ValidationErrorNotValidYet != 0 {
                return nil, TokenNotValidYet
            } else {
                return nil, TokenInvalid
            }
        }
    }
    if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid {
        return claims, nil
    }
    return nil, TokenInvalid
}

func (j *JWT) RefreshToken(tokenString string) (string, error) {
    jwt.TimeFunc = func() time.Time {
        return time.Unix(0, 0)
    }
    token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
        return j.SigningKey, nil
    })
    if err != nil {
        return "", err
    }
    if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid {
        jwt.TimeFunc = time.Now
        claims.StandardClaims.ExpiresAt = time.Now().Add(1 * time.Hour).Unix()
        return j.CreateToken(*claims)
    }
    return "", TokenInvalid
}

api.go 路由处理

package api

import (
    "github.com/gin-gonic/gin"
    "net/http"
    myjwt "ColdChainServer/middleware/jwt"
    jwtgo "github.com/dgrijalva/jwt-go"
    "time"
    "log"
    "ColdChainServer/module"
)

func Test(c *gin.Context){
    c.JSON(http.StatusOK,gin.H{
        "message":"hello",
    })
}

func GetDataByTime(c *gin.Context) {
    isPass := c.GetBool("isPass")
    if !isPass {
        return
    }
    claims := c.MustGet("claims").(*myjwt.CustomClaims)
    if claims != nil {
        c.JSON(http.StatusOK, gin.H{
            "status": 0,
            "msg":    "token有效",
            "data":   claims,
        })
    }
}

type LoginResult struct{
    Token string `json:"token"`
    module.User
}
// 登录
func Login(c *gin.Context) {
    var loginReq module.LoginReq
    if c.BindJSON(&loginReq) == nil{
        isPass,user,err := module.LoginCheck(loginReq)
        if isPass {
            generateToken(c,user)
        }else {
            c.JSON(http.StatusOK,gin.H{
                "status":-1,
                "msg":"验证失败"+err.Error(),
            })
            return
        }
    }else{
        c.JSON(http.StatusOK,gin.H{
            "status":-1,
            "msg":"json 解析失败",
        })
        return
    }


}
// 生成令牌
func generateToken(c *gin.Context, user module.User) {
    j := &myjwt.JWT{
        []byte("newtrekWang"),
    }

    claims := myjwt.CustomClaims{
        user.Id,
        user.Name,
        user.Phone,
        jwtgo.StandardClaims{
            NotBefore: int64(time.Now().Unix() - 1000),// 签名生效时间
            ExpiresAt: int64(time.Now().Unix() + 3600),// 过期时间 一小时
            Issuer: "newtrekWang",//签名的发行者
        },
    }

    token, err := j.CreateToken(claims)

    if err != nil {
        c.JSON(http.StatusOK,gin.H{
            "status":-1,
            "msg":err.Error(),
        })
        return
    }

    log.Println(token)

    data := LoginResult{
        User:user,
        Token:token,
    }
    c.JSON(http.StatusOK,gin.H{
        "status":0,
        "msg":"登录成功!",
        "data":data,
    })
    return
}

main.go 路由分发

package main

import (
    "github.com/gin-gonic/gin"

    "ColdChainServer/api"
    "ColdChainServer/middleware/jwt"
)

func main() {
    r := gin.Default()
    r.GET("/",api.Test)
    r.POST("/login",api.Login)
    r.POST("/register",api.Register)
    r.POST("/editUser",api.UpdateUser)

    taR := r.Group("/data")
    taR.Use(jwt.JWTAuth())

    {
        taR.GET("/dataByTime",api.GetDataByTime)
    }
    r.Run(":8080")
}

验证功能

登录

登录

登录成功结果

请求需要token的接口

携带token


携带token请求结果

未携带token


image.png

无效token
image.png
目录
相关文章
|
9天前
|
JSON 安全 Go
Go语言中使用JWT鉴权、Token刷新完整示例,拿去直接用!
本文介绍了如何在 Go 语言中使用 Gin 框架实现 JWT 用户认证和安全保护。JWT(JSON Web Token)是一种轻量、高效的认证与授权解决方案,特别适合微服务架构。文章详细讲解了 JWT 的基本概念、结构以及如何在 Gin 中生成、解析和刷新 JWT。通过示例代码,展示了如何在实际项目中应用 JWT,确保用户身份验证和数据安全。完整代码可在 GitHub 仓库中查看。
44 1
|
2月前
|
存储 中间件 API
ThinkPHP 集成 jwt 技术 token 验证
本文介绍了在ThinkPHP框架中集成JWT技术进行token验证的流程,包括安装JWT扩展、创建Token服务类、编写中间件进行Token校验、配置路由中间件以及测试Token验证的步骤和代码示例。
ThinkPHP 集成 jwt 技术 token 验证
|
1月前
|
存储 JSON 算法
JWT令牌基础教程 全方位带你剖析JWT令牌,在Springboot中使用JWT技术体系,完成拦截器的实现 Interceptor (后附源码)
文章介绍了JWT令牌的基础教程,包括其应用场景、组成部分、生成和校验方法,并在Springboot中使用JWT技术体系完成拦截器的实现。
79 0
JWT令牌基础教程 全方位带你剖析JWT令牌,在Springboot中使用JWT技术体系,完成拦截器的实现 Interceptor (后附源码)
|
2月前
|
JSON 安全 数据安全/隐私保护
从0到1搭建权限管理系统系列三 .net8 JWT创建Token并使用
【9月更文挑战第22天】在.NET 8中,从零开始搭建权限管理系统并使用JWT(JSON Web Tokens)创建Token是关键步骤。JWT是一种开放标准(RFC 7519),用于安全传输信息,由头部、载荷和签名三部分组成。首先需安装`Microsoft.AspNetCore.Authentication.JwtBearer`包,并在`Program.cs`中配置JWT服务。接着,创建一个静态方法`GenerateToken`生成包含用户名和角色的Token。最后,在控制器中使用`[Authorize]`属性验证和解析Token,从而实现身份验证和授权功能。
146 3
|
3月前
|
API
【Azure Developer】记录一段验证AAD JWT Token时需要设置代理获取openid-configuration内容
【Azure Developer】记录一段验证AAD JWT Token时需要设置代理获取openid-configuration内容
|
3月前
|
JSON Java API
【Azure Developer】如何验证 Azure AD的JWT Token (JSON Web 令牌)?
【Azure Developer】如何验证 Azure AD的JWT Token (JSON Web 令牌)?
|
3月前
|
JSON 算法 API
【Azure API 管理】APIM 配置Validate-JWT策略,验证RS256非对称(公钥/私钥)加密的Token
【Azure API 管理】APIM 配置Validate-JWT策略,验证RS256非对称(公钥/私钥)加密的Token
|
3月前
|
存储 开发框架 JSON
ASP.NET Core 标识(Identity)框架系列(二):使用标识(Identity)框架生成 JWT Token
ASP.NET Core 标识(Identity)框架系列(二):使用标识(Identity)框架生成 JWT Token
|
3月前
|
Java Spring
JWT token验证后,通过 ThreadLocal 进行传值
JWT token验证后,通过 ThreadLocal 进行传值
54 0
|
3月前
|
SQL Java 测试技术
在Spring boot中 使用JWT和过滤器实现登录认证
在Spring boot中 使用JWT和过滤器实现登录认证
239 0
下一篇
无影云桌面