user_controller使用通用token逻辑
This commit is contained in:
		
							
								
								
									
										1
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								go.mod
									
									
									
									
									
								
							| @@ -43,6 +43,7 @@ require ( | |||||||
| 	github.com/pelletier/go-toml/v2 v2.2.2 // indirect | 	github.com/pelletier/go-toml/v2 v2.2.2 // indirect | ||||||
| 	github.com/pmezard/go-difflib v1.0.0 // indirect | 	github.com/pmezard/go-difflib v1.0.0 // indirect | ||||||
| 	github.com/rogpeppe/go-internal v1.14.1 // indirect | 	github.com/rogpeppe/go-internal v1.14.1 // indirect | ||||||
|  | 	github.com/stretchr/objx v0.5.2 // indirect | ||||||
| 	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect | 	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect | ||||||
| 	github.com/ugorji/go/codec v1.2.12 // indirect | 	github.com/ugorji/go/codec v1.2.12 // indirect | ||||||
| 	go.uber.org/multierr v1.10.0 // indirect | 	go.uber.org/multierr v1.10.0 // indirect | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								go.sum
									
									
									
									
									
								
							| @@ -72,6 +72,7 @@ github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7 | |||||||
| github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||||
| github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= | ||||||
| github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= | github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= | ||||||
|  | github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= | ||||||
| github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= | github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= | ||||||
| github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= | ||||||
| github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||||||
|   | |||||||
| @@ -2,31 +2,29 @@ package user | |||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"net/http" | 	"net/http" | ||||||
| 	"time" |  | ||||||
|  |  | ||||||
| 	"git.huangwc.com/pig/pig-farm-controller/internal/app/controller" | 	"git.huangwc.com/pig/pig-farm-controller/internal/app/controller" | ||||||
|  | 	"git.huangwc.com/pig/pig-farm-controller/internal/app/service/token" | ||||||
| 	"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs" | 	"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs" | ||||||
| 	"git.huangwc.com/pig/pig-farm-controller/internal/infra/models" | 	"git.huangwc.com/pig/pig-farm-controller/internal/infra/models" | ||||||
| 	"git.huangwc.com/pig/pig-farm-controller/internal/infra/repository" | 	"git.huangwc.com/pig/pig-farm-controller/internal/infra/repository" | ||||||
| 	"github.com/gin-gonic/gin" | 	"github.com/gin-gonic/gin" | ||||||
| 	"github.com/golang-jwt/jwt/v5" |  | ||||||
| 	"gorm.io/gorm" | 	"gorm.io/gorm" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // jwtSecret 是用于签名 JWT 的密钥。在生产环境中,这应该从环境变量或安全配置中读取。 |  | ||||||
| var jwtSecret = []byte("your_super_secret_jwt_key") |  | ||||||
|  |  | ||||||
| // Controller 用户控制器 | // Controller 用户控制器 | ||||||
| type Controller struct { | type Controller struct { | ||||||
| 	userRepo repository.UserRepository | 	userRepo     repository.UserRepository | ||||||
| 	logger   *logs.Logger | 	logger       *logs.Logger | ||||||
|  | 	tokenService token.TokenService // 注入 token 服务 | ||||||
| } | } | ||||||
|  |  | ||||||
| // NewController 创建用户控制器实例 | // NewController 创建用户控制器实例 | ||||||
| func NewController(userRepo repository.UserRepository, logger *logs.Logger) *Controller { | func NewController(userRepo repository.UserRepository, logger *logs.Logger, tokenService token.TokenService) *Controller { | ||||||
| 	return &Controller{ | 	return &Controller{ | ||||||
| 		userRepo: userRepo, | 		userRepo:     userRepo, | ||||||
| 		logger:   logger, | 		logger:       logger, | ||||||
|  | 		tokenService: tokenService, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -55,24 +53,6 @@ type LoginResponse struct { | |||||||
| 	Token    string `json:"token"` | 	Token    string `json:"token"` | ||||||
| } | } | ||||||
|  |  | ||||||
| // generateToken 为给定用户生成 JWT |  | ||||||
| func generateToken(userID uint, username string) (string, error) { |  | ||||||
| 	expirationTime := time.Now().Add(24 * time.Hour) // Token 24 小时后过期 |  | ||||||
| 	claims := jwt.MapClaims{ |  | ||||||
| 		"user_id":  userID, |  | ||||||
| 		"username": username, |  | ||||||
| 		"exp":      expirationTime.Unix(), |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) |  | ||||||
| 	tokenString, err := token.SignedString(jwtSecret) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return "", err |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return tokenString, nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // CreateUser 处理创建用户的请求 | // CreateUser 处理创建用户的请求 | ||||||
| func (c *Controller) CreateUser(ctx *gin.Context) { | func (c *Controller) CreateUser(ctx *gin.Context) { | ||||||
| 	var req CreateUserRequest | 	var req CreateUserRequest | ||||||
| @@ -134,7 +114,7 @@ func (c *Controller) Login(ctx *gin.Context) { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// 登录成功,生成 JWT token | 	// 登录成功,生成 JWT token | ||||||
| 	tokenString, err := generateToken(user.ID, user.Username) | 	tokenString, err := c.tokenService.GenerateToken(user.ID) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		c.logger.Errorf("Login: 生成 token 失败: %v", err) | 		c.logger.Errorf("Login: 生成 token 失败: %v", err) | ||||||
| 		controller.SendErrorResponse(ctx, http.StatusInternalServerError, "登录失败,无法生成认证信息") | 		controller.SendErrorResponse(ctx, http.StatusInternalServerError, "登录失败,无法生成认证信息") | ||||||
|   | |||||||
| @@ -1,16 +1,17 @@ | |||||||
| package token | package token_test | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"testing" | 	"testing" | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
|  | 	"git.huangwc.com/pig/pig-farm-controller/internal/app/service/token" | ||||||
| 	"github.com/golang-jwt/jwt/v5" | 	"github.com/golang-jwt/jwt/v5" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func TestGenerateToken(t *testing.T) { | func TestGenerateToken(t *testing.T) { | ||||||
| 	// 使用一个测试密钥初始化 TokenService | 	// 使用一个测试密钥初始化 TokenService | ||||||
| 	testSecret := []byte("test_secret_key") | 	testSecret := []byte("test_secret_key") | ||||||
| 	service := NewTokenService(testSecret) | 	service := token.NewTokenService(testSecret) | ||||||
| 
 | 
 | ||||||
| 	userID := uint(123) | 	userID := uint(123) | ||||||
| 	tokenString, err := service.GenerateToken(userID) | 	tokenString, err := service.GenerateToken(userID) | ||||||
| @@ -46,7 +47,7 @@ func TestGenerateToken(t *testing.T) { | |||||||
| func TestParseToken(t *testing.T) { | func TestParseToken(t *testing.T) { | ||||||
| 	// 使用一个测试密钥初始化 TokenService | 	// 使用一个测试密钥初始化 TokenService | ||||||
| 	testSecret := []byte("test_secret_key") | 	testSecret := []byte("test_secret_key") | ||||||
| 	service := NewTokenService(testSecret) | 	service := token.NewTokenService(testSecret) | ||||||
| 
 | 
 | ||||||
| 	userID := uint(456) | 	userID := uint(456) | ||||||
| 
 | 
 | ||||||
| @@ -74,7 +75,7 @@ func TestParseToken(t *testing.T) { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// 测试用例 3: 过期 token (创建一个过期时间在过去的 token) | 	// 测试用例 3: 过期 token (创建一个过期时间在过去的 token) | ||||||
| 	expiredClaims := Claims{ | 	expiredClaims := token.Claims{ | ||||||
| 		UserID: userID, | 		UserID: userID, | ||||||
| 		RegisteredClaims: jwt.RegisteredClaims{ | 		RegisteredClaims: jwt.RegisteredClaims{ | ||||||
| 			ExpiresAt: jwt.NewNumericDate(time.Now().Add(-time.Hour)), // 1 小时前 | 			ExpiresAt: jwt.NewNumericDate(time.Now().Add(-time.Hour)), // 1 小时前 | ||||||
		Reference in New Issue
	
	Block a user