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的error和interface{}
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的实现
如果帮助到您,点点赞哈!