简介

JSON Web Token(JWT)技术是一种编码字符串或令牌,包含无限的信息,URL安全,用于API身份验证。它是加密签名的。JWT身份验证的最大优点是令牌一旦发送,中间人就无法攻击和修改令牌。主要是JWT用于认证和发送机密信息。JWT使用了不同的算法(如HMAC、RSA)作为私钥/公钥进行数字签名。

JWT结构

  • Header
    • 主要包括算法和token类型,主要是jwt
  • 有效载荷
    • 包含数据信息
  • 签名
    • 它需要标头和有效负载进行编码。它验证令牌不会更改或受到攻击
  1. package main
  2. import (
  3. "errors"
  4. "fmt"
  5. "net/http"
  6. "os"
  7. "time"
  8. "github.com/dgrijalva/jwt-go"
  9. "github.com/gin-gonic/gin"
  10. )
  11. // Title JWT SERVER
  12. // JWT只能在过期时失效
  13. // JWT过期后需要重新登录,会导致用户体验差,可以通过Redis存储JWT,实现JWT刷新
  14. // JWT可能会被黑客劫持,实现一个一键注销功能,不需要等待过期
  15. /**
  16. * jwt.StandardClaims 声明
  17. */
  18. type AuthRoleClaims struct {
  19. v interface{}
  20. Method *JWTMethod
  21. jwt.StandardClaims
  22. }
  23. type JWTMethod struct {
  24. ExpiresAt int64
  25. Issuer string
  26. key string
  27. }
  28. type JWTService interface {
  29. //生成TOKEN
  30. GeneratorToken(phone string) string
  31. //验证TOKEN
  32. ValidatedToken(jwtToken string) (*jwt.Token, error)
  33. //刷新TOKEN
  34. RefreshToken(jwtToken string) (*jwt.Token, error)
  35. //注销TOKEN
  36. DeleteToken(jwtToken string) (*jwt.Token, error)
  37. }
  38. // jwt.NewWithClaims 生成JWT
  39. // jwt.NewWithClaims 方法根据 Claims 结构体创建 Token 示例。
  40. // param 1 jwt.SigningMethod {jwt.SigningMethodHS256, HS384, HS512}
  41. // param 2 StandardClaim 自定义类型
  42. /**
  43. type StandardClaims struct {
  44. Audience string `json:"aud,omitempty"`
  45. ExpiresAt int64 `json:"exp,omitempty"`
  46. Id string `json:"jti,omitempty"`
  47. IssuedAt int64 `json:"iat,omitempty"`
  48. Issuer string `json:"iss,omitempty"`
  49. NotBefore int64 f `json:"nbf,omitempty"`
  50. Subject string `json:"sub,omitempty"`
  51. }
  52. */
  53. func (auth *AuthRoleClaims) GeneratorToken() string {
  54. claims := &AuthRoleClaims{
  55. v: auth.v,
  56. StandardClaims: jwt.StandardClaims{
  57. ExpiresAt: auth.Method.ExpiresAt,
  58. Issuer: auth.Method.Issuer,
  59. IssuedAt: time.Now().Unix(),
  60. },
  61. }
  62. token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
  63. //编码为String
  64. jwt, err := token.SignedString([]byte(auth.Method.key))
  65. if err != nil {
  66. panic(err)
  67. }
  68. return jwt
  69. }
  70. func (auth *JWTMethod) ValidatedToken(jwtToken string) (*jwt.Token, error) {
  71. return jwt.Parse(jwtToken, func(token *jwt.Token) (interface{}, error) {
  72. if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
  73. return nil, fmt.Errorf("Invalid token", token.Header)
  74. }
  75. return []byte(jwtToken), nil
  76. })
  77. }
  78. //全局变量
  79. var (
  80. START_PORT = "8080"
  81. )
  82. type WebGroup struct {
  83. Version uint
  84. GroupPath string
  85. }
  86. type LoginInfo struct {
  87. Phone string `json:"phone"`
  88. Password string `json:"password"`
  89. }
  90. func ResponseStatus(status int) string {
  91. switch status {
  92. case 200:
  93. return "Success"
  94. case 400:
  95. return "User operatal error"
  96. case 500:
  97. return "Server Error"
  98. }
  99. return ""
  100. }
  101. func LoginServer() gin.HandlerFunc {
  102. return func(ctx *gin.Context) {
  103. login := &LoginInfo{}
  104. if err := ctx.ShouldBindJSON(login); err != nil {
  105. ctx.JSON(http.StatusBadRequest, gin.H{
  106. "msg": ResponseStatus(http.StatusBadRequest)})
  107. }
  108. secret := os.Getenv("SECRET")
  109. if secret == "" {
  110. ctx.JSON(http.StatusInternalServerError,
  111. errors.New("Error"))
  112. }
  113. claims := &AuthRoleClaims{
  114. v: login.Phone,
  115. Method: &JWTMethod{
  116. ExpiresAt: time.Now().Add(time.Second * 5).Unix(),
  117. Issuer: "user",
  118. key: secret,
  119. },
  120. }
  121. token := claims.GeneratorToken()
  122. ctx.JSON(http.StatusOK, gin.H{
  123. "jwtToken": token})
  124. }
  125. }
  126. func RegisterServer() gin.HandlerFunc {
  127. return func(ctx *gin.Context) {
  128. register := &LoginInfo{}
  129. if err := ctx.ShouldBindJSON(register); err != nil {
  130. ctx.JSON(http.StatusBadRequest, gin.H{
  131. "msg": ResponseStatus(http.StatusBadRequest)})
  132. }
  133. if len(register.Phone) != 11 || len(register.Password) <= 6 {
  134. ctx.JSON(http.StatusBadRequest, gin.H{
  135. "msg": ResponseStatus(http.StatusBadRequest)})
  136. }
  137. ctx.JSON(http.StatusOK, gin.H{
  138. "msg": ResponseStatus(http.StatusBadRequest)})
  139. }
  140. }
  141. ///AUTH FUNCTIONS
  142. func InitializeAuthServer(engine *gin.Engine) {
  143. group := &WebGroup{
  144. Version: 1,
  145. GroupPath: "/login",
  146. }
  147. v1 := engine.Group(group.GroupPath)
  148. v1.POST("/login", LoginServer())
  149. v1.POST("/registher", RegisterServer())
  150. }
  151. func SetupRouter() *gin.Engine {
  152. //初始化Gin服务
  153. server := gin.New()
  154. //注册验证服务
  155. InitializeAuthServer(server)
  156. return server
  157. }
  158. func amain() {
  159. router := SetupRouter()
  160. router.Run(":" + START_PORT)
  161. }