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的实现

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

相关推荐
追逐时光者2 小时前
免费、简单、直观的数据库设计工具和 SQL 生成器
后端·mysql
初晴~2 小时前
【Redis分布式锁】高并发场景下秒杀业务的实现思路(集群模式)
java·数据库·redis·分布式·后端·spring·
盖世英雄酱581362 小时前
InnoDB 的页分裂和页合并
数据库·后端
小_太_阳3 小时前
Scala_【2】变量和数据类型
开发语言·后端·scala·intellij-idea
直裾3 小时前
scala借阅图书保存记录(三)
开发语言·后端·scala
星就前端叭3 小时前
【开源】一款基于Vue3 + WebRTC + Node + SRS + FFmpeg搭建的直播间项目
前端·后端·开源·webrtc
小林coding4 小时前
阿里云 Java 后端一面,什么难度?
java·后端·mysql·spring·阿里云
AI理性派思考者4 小时前
【保姆教程】手把手教你在Linux系统搭建早期alpha项目cysic的验证者&证明者
后端·github·gpu
从善若水5 小时前
【2024】Merry Christmas!一起用Rust绘制一颗圣诞树吧
开发语言·后端·rust