(基础)golang+jwt实现用户登录获取token
-
1.根据用户名/密码获取token Service
JWT(JSON Web Token)
是一个非常轻巧的规范。这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息。一个JWT由三部分组成,<font color='red'>头部、载荷 与 签名</font>。
JWT原理类似我们加盖公章或手写签名的的过程,合同上写了很多条款,不是随便一张纸随便写啥都可以的,必须要一些证明,比如签名,比如盖章。JWT就是通过附加签名,保证传输过来的信息是真的,而不是伪造的;
载荷:
包含生成Token时间,过期时间,以及一些身份标识,标准定义了6个字段,载荷json经过base64编码后得到JWT的载荷:
Payload载荷: jti:该jwt的唯一标识 iss:该jwt的签发者 iat:该jwt的签发时间 aud:该jwt的接收者 sub:该jwt的面向的用户 nbf:该jwt的生效时间,可不设置,若设置,一定要大于当前Unix UTC,否则token将会延迟生效 exp:该jwt的过期时间 可自定义其他key-value形式的数据作为载体
签名:
将头部和载荷用'.'号连接,再加上一串密钥,经过头部声明的加密算法加密后得到签名
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret )
JWT Token
Token=头部+'.'+载荷+'.'+签名
基本数据结构
上面是签名的使用例子,下面分析签名的源码实现,首先看下数据结构Token,包含了我们标准中说道的三部分:头部,载荷和签名,此外还带了一个用于存储生成token的字段Raw和校验标识符Valid
// A JWT Token. Different fields will be used depending on whether you're // creating or parsing/verifying a token. type Token struct { Raw string // The raw token. Populated when you Parse a token Method SigningMethod // The signing method used or to be used Header map[string]interface{} // The first segment of the token Claims Claims // The second segment of the token Signature string // The third segment of the token. Populated when you Parse a token Valid bool // Is the token valid? Populated when you Parse/Verify a token }
==定义密钥==
var tokenApiSecretKey="itxjTokenApi980420"
获取token
//get token
func GetTokenService(name string,pwd string)(string,error){
//非空校验
if common.IsEmpty(name) || common.IsEmpty(pwd) {
return "",errors.New("账号,密码不能为空")
}
token := jwt.New(jwt.SigningMethodHS256)
claims:=make(jwt.MapClaims)
claims["jti"]=time.Now().Unix()
claims["iss"]="itxj"
claims["iat"]=time.Now()
claims["aud"]="mam"
claims["sub"]=name
claims["nbf"]=time.Now().Unix()
claims["exp"]=time.Now().Add(time.Hour*time.Duration(24)).Unix()
claims["cs"]="this is cs claims"
token.Claims=claims
tokenStr, err := token.SignedString([]byte(tokenApiSecretKey))
if err!=nil {
return "",err
}
return tokenStr,nil
}
校验token
//校验token
func ValidateTokenService(tokenStr string)(bool,error){
token, errByParseToken := jwt.Parse(tokenStr, func(token *jwt.Token) (i interface{}, e error) {
return []byte(tokenApiSecretKey),nil
})
if errByParseToken!=nil {
return false,errors.New("An invalid Token ")
}
if !token.Valid {
return false,errors.New("fail while invalid Token ")
}
return true,nil
}
> 获取校验成功后的token(*jwt.Token)
>
>
//获取校验并且返回token
func GetValidateTokenService(tokenStr string)(*jwt.Token,error){
token, er := jwt.Parse(tokenStr, func(token *jwt.Token) (i interface{}, e error) {
return []byte(tokenApiSecretKey), nil
})
if er!=nil {
return token,er
}
return token,nil
}
校验成功后根据key获取token中载荷的数据
//从token claims中提取数据
func GetValFormTokenClaims(key string,claims jwt.Claims)string{
v := reflect.ValueOf(claims)
if v.Kind() == reflect.Map {
for _, k := range v.MapKeys() {
value := v.MapIndex(k)
if fmt.Sprintf("%s", k.Interface()) == key {
return fmt.Sprintf("%v", value.Interface())
}
}
}
return ""
}
-
2.测试
//获取token tokenStr, errByGetToken := service.GetTokenService("itxj", "itxj") if errByGetToken!=nil { fmt.Printf("Get Token error......%s",errByGetToken.Error()) return } fmt.Printf("token=%s\n",tokenStr) //校验token isValidate, errByParseToken := service.ValidateTokenService(tokenStr) if errByParseToken!=nil { fmt.Printf("Validate Token error......%s",errByParseToken.Error()) return } fmt.Printf("token is =%v\n",isValidate) //获取校验成功的token token, errByGetParseToken := service.GetValidateTokenService(tokenStr) if errByGetParseToken!=nil{ fmt.Printf("Get Validate Token error......%s",errByGetParseToken.Error()) return } claims := token.Claims fmt.Printf("token.sub=%s;\n",service.GetValFormTokenClaims("sub",claims)) fmt.Printf("token.cs=%s;\n",service.GetValFormTokenClaims("cs",claims))
码字不易,还望各位哥哥姐姐们关注点赞支持一下