当前位置:首页 > 行业动态 > 正文

golang 登录验证

JWT简介

JSON Web Token(JWT)是一种开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,用于在各方之间安全地传输信息作为JSON对象,这种信息可以被验证和信任,因为它是数字签名的,JWT可以确保消息的完整性和身份验证,因此它们被广泛用于身份验证和授权场景。

Golang使用JWT进行身份验证的最佳实践

1、安装依赖库

在开始使用JWT之前,我们需要安装一些依赖库,在Golang中,我们可以使用github.com/dgrijalva/jwt-go库来处理JWT相关操作,通过以下命令安装依赖库:

go get -u github.com/dgrijalva/jwt-go

2、生成Token

要生成一个JWT Token,我们需要创建一个jwt.Token实例,并设置一些相关的声明(claims),以下是一个简单的示例:

package main
import (
 "fmt"
 "time"
 "github.com/dgrijalva/jwt-go"
)
func main() {
 // 创建一个签名密钥
 key := []byte("my_secret_key")
 // 创建一个新的token实例
 token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
  "exp": time.Now().Add(time.Hour * 72).Unix(), // 设置过期时间为1小时后
  "nbf": time.Now().Unix(),                   // 设置生效时间为现在
  "sub": "123456",                           // 设置用户ID为123456
 })
 // 使用签名密钥对token进行签名
 tokenString, err := token.SignedString(key)
 if err != nil {
  fmt.Println("Error signing token:", err)
  return
 }
 fmt.Println("Generated Token:", tokenString)
}

3、解析Token

要解析一个JWT Token,我们需要使用jwt.ParseWithClaims函数,这个函数会返回一个*jwt.Token实例和一个错误,如果解析成功,我们可以通过访问Claims()方法来获取声明(claims),以下是一个简单的示例:

package main
import (
 "fmt"
 "time"
 "github.com/dgrijalva/jwt-go"
)
func main() {
 // 创建一个签名密钥
 key := []byte("my_secret_key")
 tokenString := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ" // 从上文生成的Token字符串替换这里
 claims := &jwt.StandardClaims{} // 创建一个空的声明实例
 _, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) { // 使用签名密钥验证token的签名
  if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { // 如果签名方法不是HMAC,则返回错误和nil值
   return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
  } else if _, ok := token.SigningKey.(*jwt.HMAC); !ok || len(token.SigningKey) != len(key) { // 如果签名密钥不是HMAC或者长度不等于我们设置的密钥长度,则返回错误和nil值
   return nil, fmt.Errorf("invalid signing key: %v", token.SigningKey)
  } else if claims, ok := token.Claims.(*jwt.StandardClaims); ok && token.Valid { // 如果声明类型正确且token有效,则返回nil值和声明实例本身
   return claims, nil
  } else if claims, ok := token.Claims.(*jwt.RefreshableClaims); ok && token.Valid { // 如果声明类型正确且token有效且是RefreshableClaims类型,则返回nil值和声明实例本身以及刷新令牌(如果有的话)
   return claims, nil, token.RefreshToken
  } else if claims, ok := token.Claims.(*jwt.UnverifiableClaims); ok && token.Valid && len(token.Raw) > 0 && token != nil && tokenString == token.Raw { // 如果声明类型正确且token有效且是非可验证的声明类型、原始token字符串与生成的token字符串相同且token不为nil,则返回nil值、声明实例本身以及原始token字符串(作为刷新令牌)
   return claims, nil, tokenString + "+" + claims.ExpiresAt.Sub(time.Now()).String() + "+" + claims.Issuer + "+" + claims.Subject + "+" + claims.Audience[0] + "+" + claims.Jti + "+" + claims.NotBefore + "+" + claims.Nbf + "+" + claims.Expiration + "+" + claims.IssuedAt + "+" + claims.Id + "+" + claims.Username + "+" + claims.Email + "+" + claims.Role + "+" + claims.Gender + "+" + claims["custom_field"] // 将其他自定义字段添加到这里,用"+"连接各个字段值和分隔符字符串拼接成完整的刷新令牌字符串
  } else if isExpiredToken(token) && token != nil && tokenString == token.Raw && len(tokenString) > len("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9") && len(tokenString) < len("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ") && len(claimsBytes, err) > len("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9") && len(claimsBytes, err) < len("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ") && len(claimsBytes, err) > len("eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9") && len(claimsBytes, err) < len("eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Imh0dHBzOlw6YWRtaW4ucGFzc3dvcmQvc2VudDpteS1hc3NldHMtc2VyaWFsaXplZGtleSI6ICItaWQgdGV4dC1hcmtldCBmcm9tIFZhbHVlLCBXb3JsZCEnKTogVGV4dC1hdGVkIGFuZCBkaXN0IGlkLGNvbmNhdCgxKzEpICgyNCBleGFtcGxlLnRlc3QpbiBiYXNlNjQgc3RyaW5nIGNvbnRlbnRzIE1hbnVzaCwgSW1hZ2VDLWRmaWxlcyBXb3JsZCkgVmlldzENCiAgICAgICAgICAgaHR0cHM6Ly9naXRodWIuY29tL2FwaXRvcmlmeSBleGFtcGxlLnRlc3QpbiBiYXNlNjQgc3RyaW5nIGNvbnRlbnRzIE1hbnVzaCggaGVyb3
0

相关推荐

  • Mongo MapReduce实例,对接Mongo数据库的典型应用场景有哪些?
  • 在安装MongoDB时,mongod进程的具体操作步骤有哪些需要注意?
  • MongoDB文档数据库云服务,如何利用MongoDB提升数据存储与管理效率?
  • 如何实现Mongo MapReduce与Mongo的对接?
  • MongoDB数据库是否需要收费?文档数据库(MongoDB)的费用结构是怎样的?
  • persistentvolumeclaim binding_PersistentVolumeClaim
  • 如何取消织梦后台登录时的验证码验证?
  • 如何在系统中顺利安装 Golang?
  • Golang如何部署到服务器上?
  • 解决Golang无法启动的故障排查指南
  • How Can Inspiring English Quotes Enhance the Impact of a NanjingBased English Website?
  • 为何我在尝试登录织梦后台时总是收到验证码不正确的提示,导致无法成功登录?
  • boll m源码的原创疑问句标题可以是,,如何获取并分析Boll M指标的源代码?
  • 如何解决MySQL中的1048错误代码,即Column column_name cannot be null?
  • playbook role_ROLE
  • 最新文章

    随机文章