JWT是json web token缩写。它将用户信息加密到token里,服务器不保存任何用户信息。服务器通过使用保存的密钥验证token的正确性,只要正确即通过验证。
JWT 和sessions 不同 session是存储在服务器的,每次只给客户端返回sessionid,客户端每次请求时带上sessionid即可。
但是,有多台服务器时就会出现一些麻烦,需要同步多台服务器信息,session就不好处理了。因为session是保存在服务器的,会出现A服务器能获取信息,B服务器身份信息无法通过。所以JWT就能很好的解决这个问题。服务器不需要保存信息,只需要保存加密用的secret,在用户登陆后将JWT加密生成token并发送给客户端,由客户端存储,客户端每次请求带上token。让服务器进行解析并验证。
JWT构成
一、Header (头部)
Jwt的头部承载两部分信息:
声明类型,这里是jwt
声明加密的算法 通常直接使用 HMAC SHA256
二、 Playload(载荷又称为Claim)
playload可以填充两种类型数据
1.标准中注册的声明:
iss: 签发者
sub: 面向的用户
aud: 接收方
exp: 过期时间
nbf: 生效时间
iat: 签发时间
jti: 唯一身份标识
2.自定义数据
三、Signature(签名)
签名的算法:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret
)
代码实现
下载
go get -u "github.com/dgrijalva/jwt-go"
引入
import ( "errors" "fmt" "time" "github.com/dgrijalva/jwt-go" )
定义结构体
type Userinfo struct { Username string `json:"username"` Password string `json:"password"` }
1、生成token
func Macke(user *Userinfo) (token string, err error) { //生成jwt claims := jwt.MapClaims{ //创建一个自己的声明 "name": user.Username, "pwd": user.Password, "iss": "lva", "nbf": time.Now().Unix(), "exp": time.Now().Add(time.Second * 4).Unix(), "iat": time.Now().Unix(), }
then := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
fmt.Println(then) //打印&{ 0xc0000040a8 map[alg:HS256 typ:JWT] map[exp:1637212218 iat:1637212214 iss:lvjianhua name:zhansan nbf:1637212214 pwd:pwd] false}
token, err = then.SignedString([]byte("gettoken"))
return }
2、解析token
func secret() jwt.Keyfunc { //按照这样的规则解析 return func(t *jwt.Token) (interface{}, error) { return []byte("gettoken"), nil } } //解析token func ParseToken(token string) (user *Userinfo, err error) { user = &Userinfo{} tokn, _ := jwt.Parse(token, secret()) claim, ok := tokn.Claims.(jwt.MapClaims) if !ok { err = errors.New("解析错误") return } if !tokn.Valid { err = errors.New("令牌错误!") return } fmt.Println(claim) user.Username = claim["name"].(string) //强行转换为string类型 user.Password = claim["pwd"].(string) //强行转换为string类型 return }
3、实战使用
package main import ( "fmt" token "main/jwtset" ) func main() { var use = token.Userinfo{"zhansan", "pwd"} tkn, _ := token.Macke(&use) fmt.Println("_____", tkn) // time.Sleep(time.Second * 8)超过时间打印令牌错误 user, err := token.ParseToken(tkn) if err != nil { fmt.Println(err) } fmt.Println(user.Username) }
用户请求时带上token,服务器解析token后可以获得其中的用户信息,如果token有任何改动,都无法通过验证.
内容摘抄来自:https://www.jianshu.com/p/b4e0744b44e0/