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