JWT 是 Json Web Token 的缩写,是一个签名的Json对象,能够用做身份验证。Bearer
在Oauth2中一般用于令牌。令牌由三部分组成,以 .
分割。前两部分是JSON对象,并进行base64url
编码,最后一部分是签名,以相同格式编码。javascript
JWT原理:在服务器认证后,生成一个加密的 JSON 对象,即 Token 返还给用户,以后用户与服务端通讯都须要带上该 Token 令牌,服务器只依靠该令牌认定用户身份是否合法,所以服务器就不须要保存任何 session 数据了。 每当用户想要访问受保护的路由或资源时,用户代理应该使用承载模式发送JWT,一般在Authorization Header
中。Header的内容应以下所示:java
Authorization: Bearer <token>
复制代码
JWT的组成:Header.Payload.Signature
git
{
"alg":"HS256",
"typ":"JWT"
}
复制代码
alg
属性表示签名的算法为 HS256(HMAC SHA256),typ
属性表示该 Token 的类型,JWT令牌统一写为 JWT
。最后将该对象经过 Base64URL
算法转为字符串github
{
"userId":"123"
"exp":"3132134213"
"iat":"1231312323"
}
复制代码
能够在该对象中添加时间戳属性,iat
属性用来表示当前时间戳,exp
属性表示到期时间戳,有了这两个属性就能够验证 token 是否过时。该对象也要通过 Base64Url
编码算法
secret
密钥,这个密钥只有服务器知道,而后使用 Header 中指定的签名算法 生成签名,如下为 HMAC SHA256 算法建立签名:HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
复制代码
官方地址:github.com/dgrijalva/j…bash
终端下载:服务器
// 使用 go mod 的话直接在项目中 go get
go get "github.com/dgrijalva/jwt-go"
复制代码
自定义 JWT 中间件验证:session
import (
"github.com/dgrijalva/jwt-go"
jailer "github.com/iris-contrib/middleware/jwt"
)
/** * 验证 jwt * @method JwtHandler */
func JwtHandler() *jailer.Middleware {
return jailer.New(jailer.Config{
// 验证 jwt 的 token 的方法
ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) {
// 本身加密的密钥
return []byte("secret"), nil
},
SigningMethod: jwt.SigningMethodHS256,
Expiration:true,
})
}
复制代码
这样一个简单的验证 token 的中间件就写好了。让咱们看一下中间件的配置 jailer.Config JWT 中 结构体 Config 源码解析函数
type Config struct {
//返回 JWT 验证签名 密钥的函数,默认值为nil
ValidationKeyGetter jwt.Keyfunc
// 请求中用户(&令牌)信息所在的属性的名称,若是是 JWT 将会被存储,默认值为 jwt
ContextKey string
// 令牌验证出错调用的函数
ErrorHandler errorHandler
// 是否须要凭证,默认值 false
CredentialsOptional bool
//从 request 中提取 token 的函数 默认 FromAuthHeader 从 from Authorization header 中获取 token
Extractor TokenExtractor
// 设置后,全部使用OPTIONS方法的请求都将使用身份验证
//若是使用需在 路由中注册,默认值为 false
EnableAuthOnOptions bool
// 设置以后,middelware将验证是否使用特定的签名算法对令牌进行了签名,若是签名方法不是常量,可使用ValidationKeyGetter回调来实现其余检查,默认值 nil
SigningMethod jwt.SigningMethod
// 验证 令牌是否过时,若是过时返回 过时错误,默认值 false
Expiration bool
}
复制代码
在登录的时候生成 JWT Tokenui
token := jwt.New(jwt.SigningMethodHS256) // 建立 Header ,算法为 HS256
claims := make(jwt.MapClaims)
claims["exp"] = time.Now().Add(time.Hour * time.Duration(12)).Unix()// 时间戳
claims["iat"] = time.Now().Unix() // 生成时的当前时间戳
claims["user_id"] = user.Id // 自定义属性
token.Claims = claims
tokenString, err := token.SignedString([]byte("secret")) // 签名密钥
复制代码
tokenString
就是咱们获得的 Token 令牌了,在令牌中的第二部分加入了 user_id
属性,方便以后用户在登录时候的其余操做
在路由中添加 中间件验证
v1.PartyFunc("/login", func(login router.Party) {
login.Post("/user_login", controller.Login)
login.Post("/user_reg", controller.Register)
})
v1.Use(middleware.JwtHandler().Serve)
复制代码
JWT 自带验证方法,若是想再自行加入验证能够注册新的中间件,例如
// 路由验证
v1.Use(middleware.JwtHandler().Serve, middleware.AuthToken)
// middleware.AuthToken 中间件 中部分代码
func AuthToken(ctx iris.Context) {
u := ctx.Values().Get("jwt").(*jwt.Token) //获取 token 信息
userId, _ := u.Claims.(jwt.MapClaims)["user_id"]
}
复制代码
如例子,能够获取到咱们以前 存在token中的 userId 属性,以后能够进行其余操做