gin框架中JWT的使用
前言:
Token 和 Session
Session 是一种记录服务器和客户端会话状态的机制,使服务端有状态化,可以记录会话信息。
而 Token 是令牌,访问资源接口(API)时所需要的资源凭证。Token 使服务端无状态化,不会存储会话信息。
正文:
Gin JWT
基于JWT的Token认证机制实现
JSON Web Token(JWT)是一个非常轻巧的规范。
这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息,
restful api的无状态认证
JWT的组成
一个JWT实际上就是一个字符串,它由三部分组成,它们之间用圆点(.)连接
分别是:
Header 声明类型以及加密算法
Payload 存放有效信息的地方 过期时间 ….
Signature 签证信息
token示例:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJOYW1lIjoibGFtcG9sIiwiZXhwIjoxNjQyNDA5ODExLCJpYXQiOjE2NDI0MDk3NTEsInN1YiI6InVzZXIgdG9rZW4ifQ.knArw6dhbVwWMkiMzgQ3JWymFl_HU5c4-nwanO72xE8
Header jwt的头部由两部分信息组成:
type:声明类型,这里是jwt
alg:声明加密的算法 通常直接使用 HMAC SHA256
{
"type":"jwt",
"alg":"HS256"
}
安装JWT
go get -u github.com/dgrijalva/jwt-go
jwt生成token字符串
生成token代码如下:
type UserClaims struct { jwt.StandardClaims //嵌套 UserName string } var JWTKEY = []byte("asdfadsfadsf") //签名的key,任意填写即可 // 获取token func getToken(c *gin.Context) { //payload claims := UserClaims{ UserName: "lampol", StandardClaims: jwt.StandardClaims{ ExpiresAt: time.Now().Add(60 * time.Second).Unix(), //过期时间 IssuedAt: time.Now().Unix(), //签发时间 Subject: "user token", }, } token := jwt.NewWithClaims(jwt.SigningMethodHS256, &claims) tokenString, err := token.SignedString(JWTKEY) if err != nil { log.Fatal(err.Error()) } c.JSON(http.StatusOK, gin.H{ "code": 200, "msg": "get token success", "token": tokenString, }) } func main() { router := gin.Default() //定义路由 router.GET("getToken", getToken) router.Run() }
运行:http://localhost:8080/getToken 得到如下结果
{"code":200," msg":"get token success", "token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2Nzk3Mzc4OTcsImlhdCI6MTY3OTczNzgzNywic3ViIjoidXNlciB0b2tlbiIsIlVzZXJOYW1lIjoieWFuZ3BocCJ9.c7ZA1SGiZSnocFF5Y7M_kRugqJy3xsIAl3Jjcv9Axgk"}
token过期说明:
jwt的token生成出来后,过期时间未到是不会过期的。如果需要在程序中设置过期,就需要在将token加入数据库或者redis中,将对应token的值设置为过期即可
项目中:
先使用jwt进行token验证
然后再使用数据库或者redis再进行验证一次
全部通过后才可以正常使用
token解析验证
type User struct { Token string `form:"token" binding:"required"` } // 解析token func ParseToken(c *gin.Context) { var u User err := c.ShouldBind(&u) if err != nil { c.String(http.StatusOK, err.Error()) return } claims := UserClaims{} token, err := jwt.ParseWithClaims(u.Token, &claims, func(t *jwt.Token) (interface{}, error) { return JWTKEY, nil }) //解析错误 if err != nil{ c.JSON(http.StatusOK, gin.H{"code": 404, "msg": "token invalid"}) return } //验证失败 if token.Valid != true { ve, _ := err.(*jwt.ValidationError) if ve.Errors == jwt.ValidationErrorExpired { c.JSON(http.StatusOK, gin.H{"code": 404, "msg": "token expired"}) } else { c.JSON(http.StatusOK, gin.H{"code": 405, "msg": "token invalid"}) } return } //验证成功, c.JSON(http.StatusOK, gin.H{ "code" : 200, "msg" : "token valid success", "token": token, }) return } func main() { router := gin.Default() //定义路由 router.GET("getToken", getToken) router.GET("ParseToken", ParseToken) router.Run() }
完结
但行好事,莫问前程!
本文来自博客园,作者:yangphp,转载请注明原文链接:https://www.cnblogs.com/ypeih/p/17320092.html