JWT在Gin中的使用

42次阅读

共计 656 个字符,预计需要花费 2 分钟才能阅读完成。

LearnJWT in Gin for Go

介绍

JSON Web Token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于 JSON 的开放标准((RFC 7519). 该 Token 被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT 的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该 Token 也可直接被用于认证,也可被加密。

安装

使用

1. import "github.com/dgrijalva/jwt-go"
2. import "github.com/appleboy/gin-jwt"

使用 jwt-go,可操作性更好一点,参考文档:https://godoc.org/github.com/…

编写 JWT 工具包

1. 定义 Claims 结构体

2. 定义方法:GenerateToken(username, password string) (string error){}, ParseToken(token string) (*Claims, error){}

3. 编写 middleware 下的 jwt
    JWT() gin.HandlerFunc{}

如何获取 token

1. 在 models 里面定义认证模型以及验证的方法
2. 在 apis 里面编写获取用户认证信息并生成 token 的方法,

验证 token

 调用相应的 api,看是否返回 token 成功 

将中间件接入 Gin

 在 router.go 里面通过 apiv1.Use(jwt.JWT()),使用中间件 

正文完
 0

JWT 在 Gin 中的使用

43次阅读

共计 3661 个字符,预计需要花费 10 分钟才能阅读完成。

介绍
JSON Web Token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于 JSON 的开放标准((RFC 7519). 该 Token 被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT 的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该 Token 也可直接被用于认证,也可被加密。
使用
安装
go get github.com/appleboy/gin-jwt
引入
import “github.com/appleboy/gin-jwt”
我目前使用的版本是 v2.5.0.
<!– more –>
创建中间件
设计 API 对象
type API struct {
App *apps.App // 业务对象
Router *gin.Engine // 路由
JWT *jwt.GinJWTMiddleware // jwt 对象
}
中间件对象:
api.JWT = &jwt.GinJWTMiddleware{
Realm: “gin jwt”,
Key: []byte(“secret key”),
Timeout: time.Hour,
MaxRefresh: time.Hour,
PayloadFunc: func(data interface{}) jwt.MapClaims {},
Authenticator: func(c *gin.Context) (interface{}, error) {},
Authorizator: func(data interface{}, c *gin.Context) bool {},
Unauthorized: func(c *gin.Context, code int, message string) {},
TokenLookup: “header: Authorization, query: token, cookie: jwt”,
// TokenLookup: “query:token”,
// TokenLookup: “cookie:token”,
TokenHeadName: “Bearer”,
TimeFunc: time.Now,
}

Realm JWT 标识

Key 服务端密钥

Timeout token 过期时间

MaxRefresh token 更新时间

PayloadFunc 添加额外业务相关的信息

Authenticator 在登录接口中使用的验证方法,并返回验证成功后的用户对象。

Authorizator 登录后其他接口验证传入的 token 方法

Unauthorized 验证失败后设置错误信息

TokenLookup 设置 token 获取位置,一般默认在头部的 Authorization 中,或者 query 的 token 字段,cookie 中的 jwt 字段。

TokenHeadName Header 中 token 的头部字段,默认常用名称 Bearer。

TimeFunc 设置时间函数

注册阶段
在注册时如果要直接返回 token,那么可以调用 TokenGenerator 来生成 token。
token, expire, err := c.JWT.TokenGenerator(strconv.Itoa(user.ID), *user)
TokenGenerator 的具体实现
func (mw *GinJWTMiddleware) TokenGenerator(userID string, data interface{}) (string, time.Time, error) {
// 根据签名算法创建 token 对象
token := jwt.New(jwt.GetSigningMethod(mw.SigningAlgorithm))
// 获取 claims
claims := token.Claims.(jwt.MapClaims)

// 设置业务中需要的额外信息
if mw.PayloadFunc != nil {
for key, value := range mw.PayloadFunc(data) {
claims[key] = value
}
}

// 过期时间
expire := mw.TimeFunc().UTC().Add(mw.Timeout)
claims[“id”] = userID
claims[“exp”] = expire.Unix()
claims[“orig_iat”] = mw.TimeFunc().Unix()
// 生成 token
tokenString, err := mw.signedString(token)
if err != nil {
return “”, time.Time{}, err
}

return tokenString, expire, nil
}
登录阶段
登录时会调用 Authenticator 注册的方法。
func (api *API) LoginAuthenticator(ctx *gin.Context) (interface{}, error) {
var params model.UserParams
if err := ctx.Bind(&params); err != nil {
return “”, jwt.ErrMissingLoginValues
}

// 根据用户名获取用户
user, err := api.App.GetUserByName(params.Username)
if err != nil {
return nil, err
}

// 验证密码
if user.AuthPassword(params.Password) {
return *user, nil
}

return nil, jwt.ErrFailedAuthentication
}
验证 Token
其他接口在设置了中间件 Router.Use(api.JWT.MiddlewareFunc()) 后,通过调用 Authorizator 方法来验证。
func (api *API) LoginedAuthorizator(data interface{}, c *gin.Context) bool {
if id, ok := data.(string); ok {
return api.App.IsExistUser(id)
}
return false
}
在业务 Hander 中可以通过方法 jwt.ExtractClaims(ctx) 来获取 payload 的信息。
深入
gin-jwt 依赖的 jwt 库叫做 jwt-go。下面来介绍一下这个库。
核心的 Token 结构:
// A JWT Token. Different fields will be used depending on whether you’re
// creating or parsing/verifying a token.
type Token struct {
Raw string // The raw token. Populated when you Parse a token
Method SigningMethod // The signing method used or to be used
Header map[string]interface{} // The first segment of the token
Claims Claims // The second segment of the token
Signature string // The third segment of the token. Populated when you Parse a token
Valid bool // Is the token valid? Populated when you Parse/Verify a token
}
这个 Token 结构体是用来生成 jwt 的 token。其中 Method 是用来表示签名使用的算法。Header 是头部 jwt 的信息,还有 Claims 记录额外的信息。
然后是生成签名的方法,key 是服务端的密钥。
func (t *Token) SignedString(key interface{}) (string, error) {
var sig, sstr string
var err error
// 将 Header 和 Claims 转换成字符串然后 base64 之后拼接在一起。
if sstr, err = t.SigningString(); err != nil {
return “”, err
}
// 使用签名算法加密
if sig, err = t.Method.Sign(sstr, key); err != nil {
return “”, err
}
return strings.Join([]string{sstr, sig}, “.”), nil
}
解密 token 的对象叫做 Parser
type Parser struct {}

// 主要解析方法
func (p *Parser) ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc) (*Token, error) {}
Parser 除了验证 Token 外,还包括解码 Header 和 Claims 的内容。
资源

https://jwt.io/introduction
https://github.com/appleboy/g…
https://github.com/dgrijalva/…

正文完
 0