蛋蛋星球-客户端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

85 lines
2.3 KiB

  1. package auth
  2. import (
  3. "applet/app/utils/cache"
  4. "errors"
  5. "fmt"
  6. "github.com/dgrijalva/jwt-go"
  7. "time"
  8. )
  9. // GenToken 生成JWT
  10. func GenToken(uid int64) (string, error) {
  11. // 创建一个我们自己的声明
  12. c := JWTUser{
  13. Uid: uid,
  14. StandardClaims: jwt.StandardClaims{
  15. ExpiresAt: time.Now().Add(TokenExpireDuration).Unix(), // 过期时间
  16. Issuer: "egg_app", // 签发人
  17. },
  18. }
  19. // 使用指定的签名方法创建签名对象
  20. tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, c)
  21. // 使用指定的secret签名并获得完整的编码后的字符串token
  22. token, err := tokenClaims.SignedString(Secret)
  23. if err != nil {
  24. return "", err
  25. }
  26. // 缓存token
  27. cacheKey := fmt.Sprintf(TokenKey, uid)
  28. _, err = cache.SetEx(cacheKey, token, TokenCacheTime)
  29. if err != nil {
  30. return "", err
  31. }
  32. return token, nil
  33. }
  34. // ParseToken 解析JWT
  35. func ParseToken(tokenString string) (*JWTUser, string, error) {
  36. // 解析token
  37. token, err := jwt.ParseWithClaims(tokenString, &JWTUser{}, func(token *jwt.Token) (i interface{}, err error) {
  38. return Secret, nil
  39. })
  40. if err != nil {
  41. return nil, "", err
  42. }
  43. if claims, ok := token.Claims.(*JWTUser); ok && token.Valid { // 校验token正确性
  44. if claims.StandardClaims.ExpiresAt < time.Now().Unix() { // 校验token时效性
  45. return nil, "", errors.New("token is expired")
  46. }
  47. //TODO::单设备验证
  48. cacheKey := fmt.Sprintf(TokenKey, claims.Uid)
  49. cJwt, err1 := cache.GetString(cacheKey)
  50. if err != nil {
  51. return nil, "", err1
  52. }
  53. if cJwt != tokenString && cJwt != "" {
  54. return nil, "", errors.New("token expired")
  55. }
  56. // TODO::判断Token快过期,就创建新的token(7天)
  57. if !claims.VerifyExpiresAt(time.Now().Add(time.Hour*24*7).Unix(), false) {
  58. newToken, _ := GenToken(claims.Uid)
  59. return claims, newToken, nil
  60. }
  61. // TODO::判断缓存是否为空,若为空则填补
  62. if cJwt == "" {
  63. _, err = cache.SetEx(cacheKey, token, CalculateSecondsUntilExpiry(time.Unix(claims.ExpiresAt, 0)))
  64. if err != nil {
  65. return nil, "", err
  66. }
  67. }
  68. return claims, "", err
  69. }
  70. return nil, "", errors.New("invalid token")
  71. }
  72. // CalculateSecondsUntilExpiry 计算 Token 距离现在的过期时间还有多少秒
  73. func CalculateSecondsUntilExpiry(expiryTime time.Time) int {
  74. return int(expiryTime.Sub(time.Now()).Seconds())
  75. }