jwt是什么?
jwt全程 Json Web Token是一个开放标准,它定义了一种紧凑的,自包含的方式,用于作为Json对象在各方之间安全的传输信息。该信息可以被验证和信任,因为它是数字签名的
使用场景
授权(Authorization):这是使用Jwt的最常见场景。一旦用户登录,后续每个请求都讲包含Jwt,允许用户防范该令牌允许的路由、服务和资源。单点登录是现在广泛使用的Jwt的一个特性,因为它的开销很小,并且可以轻松使用跨域作用
信息交换(Information exchange):对于安全的在各方面之间传输信息而言,Jwt无疑是一种很好的方式,因为Jwt可以被签名,例如,公钥、私钥对,你可以确定发送人就是他们所说的那个人。另外犹豫前面是使用头和有效负载计算的,还可以验证内容没有被篡改
Jwt 的结构
Jwt由三个部分构成,他们之间用原点.来连接
- Header
- Payload
- Signature
因此,一个典型的Jwt看起来就是
xxxxxxxx.yyyyyyyyyy.zzzzzzzzzz
Header
header典型由两部分组成,token的类型“jwt”和算法名称比如hmac
{
"alg":"hs256",
"typ":"jwt"
}
Payload
payload是存放有效信息,官方建议有效信息的格式
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
Signature
signature是签名信息,签名的内容是
- header (base64后的)
- payload (base64后的)
- secret
在Go中使用jwt
go get github.com/dgrijalva/jwt-go
使用jwt
// 需要存储的payload信息
type CustomClaims struct {
ID uint
NickName string
AuthorityId uint
jwt.StandardClaims
}
// 自定义jwt使用的签名秘钥
type JWT struct {
SigningKey []byte
}
func NewJwt() *JWT {
return &JWT{SigningKey: []byte("abc")}
}
// 创建jwt
func (j *JWT)CreateToken(claims model.CustomClaims) (string,error) {
token := jwt.NewWithClaims(jwt.SigningMethodES256,claims) // 如果key is valid 错误就换成SigningMethodHS256
return token.SignedString(j.SigningKey)
}
// 解析jwt
func (j *JWT)ParseToken(tokenString string)(*model.CustomClaims,error) {
token,err := jwt.ParseWithClaims(tokenString,&model.CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
return j.SigningKey,nil
})
if err!=nil{
if ve,ok := err.(*jwt.ValidationError);ok{
if ve.Errors & jwt.ValidationErrorExpired!=0{
return nil,errors.New("expire")
}else if ve.Errors & jwt.ValidationErrorMalformed !=0 {
return nil,err
}
}
}
claims := token.Claims.(*model.CustomClaims)
return claims,nil
}
中间件引入
func JwtAuth() gin.HandlerFunc {
return func(c *gin.Context) {
token := c.Request.Header.Get("token")
if token==""{
c.JSON(http.StatusUnauthorized,map[string]string{
"msg":"请登录",
})
c.Abort()
return
}
j := NewJwt()
claims ,err := j.ParseToken(token)
if err!=nil{
}
c.Set("user",claims.ID)
c.Next()
}
}