Hertz的JWT应用实例

JWT生成

Hertz在jwt上实现了扩展,无需开发者编写token生成代码,主要要配置好token生成的配置类,调用配置类的方法即可。

jwt.HertzJWTMiddleware对象是hertz-jwt的配置类,来源于"github.com/hertz-contrib/jwt",配置类的初始化使用jwt.New()方法。具体如下:

go 复制代码
// the jwt middleware
authMiddleware, err := jwt.New(&jwt.HertzJWTMiddleware{
    Realm: "test zone",
    Key: []byte("secret key"),
    Timeout: time.Hour,
    MaxRefresh: time.Hour,
    IdentityKey: "username",
    PayloadFunc: func(data interface{}) jwt.MapClaims {
        if v, ok := data.(*model.User); ok {
            return jwt.MapClaims{
                "username": v.Username,
            }
        }
        return jwt.MapClaims{}
    },
    IdentityHandler: func(ctx context.Context, c *app.RequestContext) interface{} {
        claims := jwt.ExtractClaims(ctx, c)
        return &model.User{
            Username: claims["username"].(string),
        }
    },
    Authenticator: func(ctx context.Context, c *app.RequestContext) (interface{}, error) {
        var user model.User
        if err := c.BindAndValidate(&user); err != nil {
            return "", jwt.ErrMissingLoginValues
        }
        userID := user.Username
        password := user.Password
        if (userID == "admin" && password == "admin") || (userID == "test" && password == "test") {
            return &model.User{
                Username: userID,
                Email: "xiaoxu@qq.com",
                Phone: "1723649173",
            }, nil
        }
        return nil, jwt.ErrFailedAuthentication
    },
    Authorizator: func(data interface{}, ctx context.Context, c *app.RequestContext) bool {
        if v, ok := data.(*model.User); ok && v.Username == "admin" {
            return true
        }
        return fals
    },

    Unauthorized: func(ctx context.Context, c *app.RequestContext, code int, message string) {
        c.JSON(code, map[string]interface{}{
        "code": code,
        "message": message,
        })
    },

})

上述代码,实例化了一个jwt的配置类,并实现了配置类的方法:

  • PayloadFunc用于设置登陆成功后为向 token 中添加自定义负载信息的函数
  • IdentityHandler 用于设置获取身份信息的函数,默认与 IdentityKey 配合使用
  • Authenticator 用于设置登录时认证用户信息的函数
  • Authorizator 用于设置授权已认证的用户路由访问权限的函数

上述方法用户实现jwt的授权与认证。

JWT的生成需要使用配置类,在上述代码中构造了配置类实例authMiddleware类型为*jwt.HertzJWTMiddleware,通过实例的LoginHandler中间件方法生成Token。

go 复制代码
// token生成
authMiddleware.LoginHandler

// 初始化配置类
err = authMiddleware.MiddlewareInit()
if err != nil {
    return nil, err
}

// 配置到路由中间件
h.POST("/login", authMiddleware.LoginHandler)

在登陆api下登陆成功就会返回token了,看到该方法的源码,如下:

实际上调用Autenticator认证函数,那么认证函数写在配置类的该方法下就可以了,如下:

go 复制代码
Authenticator: func(ctx context.Context, c *app.RequestContext) (interface{}, error) {
    var user model.User
    if err := c.BindAndValidate(&user); err != nil {
        return "", jwt.ErrMissingLoginValues
    }
    userID := user.Username
    password := user.Password
    if (userID == "admin" && password == "admin") || (userID == "test" && password == "test") {
        return &model.User{
            Username: userID,
            Email: "xiaoxu@qq.com",
            Phone: "1723649173",
        }, nil
    }
    return nil, jwt.ErrFailedAuthentication
},

上述认证逻辑是写的静态的,改为查询数据库或者rpc调用即可,路由加了配置类的LoginHandler成功返回token。

上述还没完,较重要的是如何在Token中添加用户信息,Hertz-jwt中也实现了该功能。PayloadFunc方法用于认证成功后向token的负载中添加用户信息,这样在调用LoginHandler方法时返回的token就是携带用户信息的token。

官方提供了IdentityKey字段存储部分用户信息,需要存储更多时使用jwt.MapClaims类型为map[string]interface{}使用时也很简单,jwt.ExtractClaims(ctx, c)通过key取出来即可。注意需要断言一下。

JWT验证

Jwt验证就是Authentication实现登陆验证,返回Token的逻辑。在路由中通过配置类调用LoginHandler即可。

go 复制代码
Authenticator: func(ctx context.Context, c *app.RequestContext) (interface{}, error) {
    var user model.User
    if err := c.BindAndValidate(&user); err != nil {
        return "", jwt.ErrMissingLoginValues
    }
    userID := user.Username
    password := user.Password
    if (userID == "admin" && password == "admin") || (userID == "test" && password == "test") {
        return &model.User{
            Username: userID,
            Email: "xiaoxu@qq.com",
            Phone: "1723649173",
        }, nil
    }
    return nil, jwt.ErrFailedAuthentication
},

c.BindAndValidate绑定用户名与密码,查数据库,对比密码,这里需要注意的是return,这里的return,不再仅仅表示函数结束,这里的return还会调用c.JSON()方法返回return的errorinterface{}

go 复制代码
return nil, jwt.ErrFailedAuthentication
return nil, errors.New("账户或密码错误")

这里的错误可以自定义也可以直接使用hertz-jwt库的错误,就在github.com/hertz-contrib/jwt库下,如下:

JWT授权

jwt授权,请求需要携带tokenAuthorization。路由调用配置类MiddlewareFunc()方法。

客户段可以将Token放在请求头,请求体中,Hertz-jwt默认在请求头中。看MiddlewareFunc()源码可以看到,框架从请求头的Authorization字段获取,之后又调用了IdentityHandler方法。如果向写在请求体重写该方法的逻辑即可。

go 复制代码
IdentityHandler: func(ctx context.Context, c *app.RequestContext) interface{} {
    claims := jwt.ExtractClaims(ctx, c)
    return &model.User{
    Username: claims["username"].(string),
    }
},

上述方法常用于从token的负载中获取常用的参数存到context或者app.RequestContext供后续使用。

JWT中间件

配置类接口有很多,最常用的就是如下四种:

使用jwt中间件后处理注册和登陆所有接口都要使用MiddlewareFunc方法。另外配置类在使用时需要初始化MiddlewareInit

更多及代码实例请移步## JWT在Hertz的实现

如果帮助到您,点点赞哈!

相关推荐
红尘散仙41 分钟前
我把终端小说阅读器接上了 AI Agent:TRNovel 现在能用 skill 生成书源了
人工智能·后端·rust
卷毛的技术笔记2 小时前
告别硬编码!Spring AI Alibaba 实现 AI Agent 智能工具调用(Tool Calling)
java·人工智能·后端·python·spring·ai编程
会编程的土豆2 小时前
Go 语言反射(Reflection)详解
开发语言·后端·golang
喵个咪3 小时前
GoWind Toolkit Go后端代码生成 完整全流程实战
后端·go·orm
basketball6163 小时前
Go 语言从入门到进阶:4. 数组和MAP使用方法总结
开发语言·后端·golang
qq_2518364573 小时前
SpringBoot+Vue 共享电池柜管理系统 完整实现 前后端分离项目实战 完整代码
vue.js·spring boot·后端
zhangxingchao4 小时前
AI 大模型核心六:量化、Workflow 与 Agent、多轮 RAG
前端·人工智能·后端
IT_陈寒5 小时前
Vite打包时遇到的坑,原来问题出在这里
前端·人工智能·后端
ayqy贾杰6 小时前
基层管理的三板斧,在AI时代行不通了
前端·后端·团队管理
Apifox6 小时前
Apifox 5 月更新|Postman 导入优化、Runner 支持非 root 运行、请求代码自动带鉴权
前端·后端·安全