jwt.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. // Copyright 2025 Huan-Gogs Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package tool
  5. import (
  6. "crypto/rand"
  7. "fmt"
  8. "github.com/SongZihuan/huan-gogs/internal/conf"
  9. "github.com/dgrijalva/jwt-go"
  10. "time"
  11. )
  12. type Subject int
  13. const (
  14. SubjectActiveAccount Subject = 1
  15. SubjectActiveEmail Subject = 2
  16. SubjectForgetPasswd Subject = 3
  17. )
  18. var secretKey = make([]byte, 32)
  19. func init() {
  20. if _, err := rand.Read(secretKey); err != nil {
  21. panic(err)
  22. }
  23. }
  24. type Claims struct {
  25. Audience string `json:"aud,omitempty"`
  26. ExpiresAt int64 `json:"exp,omitempty"`
  27. Id int64 `json:"jti,omitempty"`
  28. Email string `json:"email,omitempty"`
  29. IssuedAt int64 `json:"iat,omitempty"`
  30. Issuer string `json:"iss,omitempty"`
  31. NotBefore int64 `json:"nbf,omitempty"`
  32. Subject Subject `json:"sub,omitempty"`
  33. }
  34. func (c *Claims) Valid() error {
  35. now := time.Now()
  36. if now.After(time.Unix(c.ExpiresAt, 0)) {
  37. return fmt.Errorf("error")
  38. }
  39. if now.Before(time.Unix(c.NotBefore, 0)) {
  40. return fmt.Errorf("error")
  41. }
  42. if now.Before(time.Unix(c.IssuedAt, 0)) {
  43. return fmt.Errorf("error")
  44. }
  45. if c.Audience != c.Email {
  46. return fmt.Errorf("error")
  47. }
  48. return nil
  49. }
  50. func NewClaims(id int64, email string, subject Subject) *Claims {
  51. now := time.Now()
  52. return &Claims{
  53. Audience: email,
  54. ExpiresAt: now.Add(time.Duration(conf.Auth.ActivateCodeLives) * time.Minute).Unix(),
  55. Id: id,
  56. Email: email,
  57. IssuedAt: now.Unix(),
  58. Issuer: conf.Server.ExternalURL,
  59. NotBefore: now.Unix(),
  60. Subject: subject,
  61. }
  62. }
  63. func (c *Claims) ToToken() (string, error) {
  64. token := jwt.NewWithClaims(jwt.SigningMethodHS256, c)
  65. //使用指定的secret签名并获得完成的编码后的字符串token
  66. return token.SignedString(secretKey)
  67. }
  68. func ParseToken(t string) (*Claims, error) {
  69. //解析token
  70. token, err := jwt.ParseWithClaims(t, &Claims{}, func(token *jwt.Token) (i interface{}, err error) {
  71. return secretKey, nil
  72. })
  73. if err != nil {
  74. return nil, err
  75. }
  76. if claims, ok := token.Claims.(*Claims); ok && claims != nil && token.Valid {
  77. return claims, nil
  78. } else if err := claims.Valid(); err != nil {
  79. return nil, err
  80. }
  81. if claims, ok := token.Claims.(*Claims); ok && claims != nil && token.Valid {
  82. if err := claims.Valid(); err != nil {
  83. return nil, err
  84. }
  85. return claims, nil
  86. }
  87. return nil, fmt.Errorf("invalid token")
  88. }