目的
对用户进行身份认证和信息交换 RFC 7519
传统方式
通过session保存对话信息,服务端返回一个session id,用户保存这个id在cookie内,然后每次请求都传给服务端
局限性
对于服务器集群难以向每个服务器共享同一session
jwt的方式是不在服务端保存session数据,数据只保存在客户端,请求时发给服务端
JWT原理
jwt结构
jwt是个很长的字符串,包含如下部分,每个部分之间用'.'来分隔
- Header(头部):通常包含两部分信息,token的类型(即JWT)和所使用的签名算法(如HMAC、SHA256或RSA)
- Payload(负载):包含所要传递的数据。这些数据被称为Claims(声明),分为三种类型:注册声明(例如,iss - 发行者、exp - 过期时间戳)、公共声明(可以自定义,但不建议包含敏感信息)、私有声明(由双方约定的信息)
- Signature(签名):对前两部分进行签名,以验证消息的发送者并确保消息在传递过程中未被篡改
- 签名需要指定一个服务器才知道的密钥,然后根据Header指定的签名算法,算出签名
Header.Payload.Signature
额外说明
头部和负载部分本身不加密,以Base64编码传输,所以任何人都可以解码,签名部分才加密,
服务端验证签名,通过则信任jwt的信息未被篡改
工作流程
- 用户使用其凭证(如用户名和密码)登录系统
- 服务端验证凭证的正确性,并创建一个包含用户信息的JWT
- JWT中的负载部分包含所需的数据(如用户ID),然后用服务器的密钥进行签名
- 服务端将此JWT返回给用户
- 用户随后的每个请求都将包含这个JWT,通常是在HTTP请求的Authorization头部中携带
- 服务端接收请求后,会验证JWT的签名并解析负载中的数据,以确定用户的身份和权限
过期时间戳的详细解释
过期时间戳是jwt标准自带标准字段exp
- 当Token被创建时,
exp
字段被设定为一个特定的未来时间点。这通常是Token创建时间加上一个预定的时间间隔 - 当服务端接收到一个请求中的JWT时,它会检查当前时间是否已经超过了Token中的
exp
时间戳 - 如果当前时间超过了
exp
时间,那么Token就被视为无效,服务端通常会拒绝该请求并要求用户重新登录或获取新的Token
时间格式的Unix纪元以来的秒数,跟大部分标准规定的一样的
GoZero中配置
详细见我的这篇文章
GoZero微服务个人探究之路(九)api文件编写总结_go zero api 文件 如何定义参数非必填-CSDN博客
在api文件的@server指定jwt:Auth即可开启jwt,但是框架只做了服务端逻辑,对于 jwt token 的生成及 refresh token 仍需要开发者自行实现
在GoZero框架中配置并启用JWT(JSON Web Token)后,框架会自动处理每个请求中的JWT验证。GoZero的JWT中间件会检查和验证请求中的Token,然后根据验证结果决定是否允许请求通过
相关代码
go中实现创建jwt token 可以使用github.com/dgrijalva/jwt-go库
// 自定义的一些Claims数据结构
type MyCustomClaims struct {UserID string `json:"user_id"`jwt.StandardClaims
}func main() {// 密钥、、var mySigningKey = []byte("mysecretkey")// 创建一个新的Claimsclaims := MyCustomClaims{"1234567890", jwt.StandardClaims{ExpiresAt: time.Now().Add(time.Hour * 24).Unix(), // 设置Token过期时间Issuer: "xxxxxx", // 设置Token的发行者},}// 创建一个Tokentoken := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)// 使用密钥签名TokentokenString, err := token.SignedString(mySigningKey)if err != nil {}
}