这是我参与「第五届青训营 」伴学笔记创作活动的第 5 天
jwt结构
JSON Web Token 由三部分组成,以点(.)分隔,分别是:
- Header(标头)
- Payload(有效负载)
- Signature(签名)
因此,JWT 通常如下所示:
xxxxxx.yyyyyyy.zzzzzzzz
Header
Header 通常由两部分组成:
- token 的类型,这里是 JWT
- 使用的签名算法,比如 HMAC、SHA256 或 RSA。
例如:
{
"alg": "HS256",
"typ": "JWT"
}
然后,将此 JSON 以 Base64Url 编码,形成 JWT 的第一部分。
Payload
token 的第二部分是有效负载,其中包含 Claims(声明)。Claims 是有关实体(通常是用户)和其他数据的声明 举一个有效负载的例子:
{
"sub": "221122112",
"name": "Mohamd Lawand",
"admin": true,
"exp": 15323232,
"iat": 14567766 // 该 token 的签发时间
}
然后,对有效负载进行 Base64Url 编码,形成 JSON Web Token 的第二部分。
除非将其加密,否则不要将机密信息放入 JWT 的 Payload 或 Header 元素中。
签名
签名使我们能够验证 token 是否有效和没被篡改。它的工作方式是获取 token 的前两部分,将 Header 和 Payload 分别编码为 Base64,然后将它们用 “.” 连接起来。然后,获取在第一部分(Header)中提供的算法并应用于上面的连接结果。
gin封装实现jwt
package main
import (
"fmt"
"net/http"
"time"
"github.com/dgrijalva/jwt-go"
"github.com/gin-gonic/gin"
)
//自定义一个字符串
var jwtkey = []byte("www.xxx.com")
var str string
type Claims struct {
UserId uint
jwt.StandardClaims
}
func main() {
r := gin.Default()
r.GET("/set", setting)
r.GET("/get", getting)
//监听端口默认为8080
r.Run(":8080")
}
//颁发token
func setting(ctx *gin.Context) {
expireTime := time.Now().Add(7 * 24 * time.Hour)
claims := &Claims{
UserId: 2,
StandardClaims: jwt.StandardClaims{
ExpiresAt: expireTime.Unix(), //过期时间
IssuedAt: time.Now().Unix(),
Issuer: "xxx", // 签名颁发者
Subject: "user token", //签名主题
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
// fmt.Println(token)
tokenString, err := token.SignedString(jwtkey)
if err != nil {
fmt.Println(err)
}
str = tokenString
ctx.JSON(200, gin.H{"token": tokenString})
}
//解析token
func getting(ctx *gin.Context) {
tokenString := ctx.GetHeader("Authorization")
//vcalidate token formate
if tokenString == "" {
ctx.JSON(http.StatusUnauthorized, gin.H{"code": 401, "msg": "权限不足"})
ctx.Abort()
return
}
token, claims, err := ParseToken(tokenString)
if err != nil || !token.Valid {
ctx.JSON(http.StatusUnauthorized, gin.H{"code": 401, "msg": "权限不足"})
ctx.Abort()
return
}
fmt.Println(111)
fmt.Println(claims.UserId)
}
func ParseToken(tokenString string) (*jwt.Token, *Claims, error) {
Claims := &Claims{}
token, err := jwt.ParseWithClaims(tokenString, Claims, func(token *jwt.Token) (i interface{}, err error) {
return jwtkey, nil
})
return token, Claims, err
}