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

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

相关推荐
爱敲代码的小冰7 分钟前
spring boot 请求
java·spring boot·后端
java小吕布1 小时前
Java中的排序算法:探索与比较
java·后端·算法·排序算法
Goboy2 小时前
工欲善其事,必先利其器;小白入门Hadoop必备过程
后端·程序员
李少兄2 小时前
解决 Spring Boot 中 `Ambiguous mapping. Cannot map ‘xxxController‘ method` 错误
java·spring boot·后端
代码小鑫2 小时前
A031-基于SpringBoot的健身房管理系统设计与实现
java·开发语言·数据库·spring boot·后端
Json____2 小时前
学法减分交管12123模拟练习小程序源码前端和后端和搭建教程
前端·后端·学习·小程序·uni-app·学法减分·驾考题库
monkey_meng3 小时前
【Rust类型驱动开发 Type Driven Development】
开发语言·后端·rust
落落落sss3 小时前
MQ集群
java·服务器·开发语言·后端·elasticsearch·adb·ruby
大鲤余3 小时前
Rust,删除cargo安装的可执行文件
开发语言·后端·rust
她说彩礼65万4 小时前
Asp.NET Core Mvc中一个视图怎么设置多个强数据类型
后端·asp.net·mvc