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: "[email protected]",
                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: "[email protected]",
            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: "[email protected]",
            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的实现

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

相关推荐
烛阴7 小时前
bignumber.js深度解析:驾驭任意精度计算的终极武器
前端·javascript·后端
服务端技术栈7 小时前
电商营销系统中的幂等性设计:从抽奖积分发放谈起
后端
你的人类朋友8 小时前
✍️Node.js CMS框架概述:Directus与Strapi详解
javascript·后端·node.js
面朝大海,春不暖,花不开8 小时前
自定义Spring Boot Starter的全面指南
java·spring boot·后端
钡铼技术ARM工业边缘计算机9 小时前
【成本降40%·性能翻倍】RK3588边缘控制器在安防联动系统的升级路径
后端
CryptoPP9 小时前
使用WebSocket实时获取印度股票数据源(无调用次数限制)实战
后端·python·websocket·网络协议·区块链
白宇横流学长9 小时前
基于SpringBoot实现的大创管理系统设计与实现【源码+文档】
java·spring boot·后端
草捏子10 小时前
状态机设计:比if-else优雅100倍的设计
后端
考虑考虑11 小时前
Springboot3.5.x结构化日志新属性
spring boot·后端·spring
涡能增压发动积11 小时前
一起来学 Langgraph [第三节]
后端