package controller import ( "crypto/sha256" "crypto/subtle" "encoding/base64" "encoding/json" "genspark2api/common/config" "net/http" "os" "time" "github.com/gin-gonic/gin" ) // 登录请求体 type LoginRequest struct { Username string `json:"username"` Password string `json:"password"` } // JWT声明结构 type JWTClaims struct { Username string `json:"username"` Exp int64 `json:"exp"` Iat int64 `json:"iat"` Iss string `json:"iss"` } // 生成JWT令牌 func generateToken(username string) (string, error) { // 创建JWT声明 nowTime := time.Now() expireTime := nowTime.Add(24 * time.Hour) // 令牌有效期为24小时 claims := JWTClaims{ Username: username, Exp: expireTime.Unix(), Iat: nowTime.Unix(), Iss: "genspark2api", } // 序列化claims为JSON claimsJSON, err := json.Marshal(claims) if err != nil { return "", err } // Base64编码payload payload := base64.RawURLEncoding.EncodeToString(claimsJSON) // 创建header header := base64.RawURLEncoding.EncodeToString([]byte(`{"alg":"HS256","typ":"JWT"}`)) // 计算签名 signatureInput := header + "." + payload // 使用API_SECRET的SHA256哈希签名 h := sha256.New() h.Write([]byte(signatureInput + config.ApiSecret)) signature := base64.RawURLEncoding.EncodeToString(h.Sum(nil)) // 组装JWT token := header + "." + payload + "." + signature return token, nil } // LoginPage 返回登录页面 func LoginPage(c *gin.Context) { c.File("./public/login.html") } // Login 处理用户登录 func Login(c *gin.Context) { // 解析请求体 var loginReq LoginRequest if err := c.ShouldBindJSON(&loginReq); err != nil { c.JSON(http.StatusBadRequest, gin.H{ "success": false, "message": "无效的请求数据", }) return } // 验证用户名 if loginReq.Username != "maltose" { c.JSON(http.StatusUnauthorized, gin.H{ "success": false, "message": "用户名或密码错误", }) return } // 获取API_SECRET作为密码 apiSecret := os.Getenv("API_SECRET") if apiSecret == "" { apiSecret = config.ApiSecret } // 如果API_SECRET包含多个值(逗号分隔),只取第一个 for i := 0; i < len(apiSecret); i++ { if apiSecret[i] == ',' { apiSecret = apiSecret[:i] break } } // 验证密码 - 使用恒定时间比较避免时序攻击 if subtle.ConstantTimeCompare([]byte(loginReq.Password), []byte(apiSecret)) != 1 { c.JSON(http.StatusUnauthorized, gin.H{ "success": false, "message": "用户名或密码错误", }) return } // 生成JWT令牌 token, err := generateToken(loginReq.Username) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "success": false, "message": "生成令牌失败", }) return } // 返回成功响应和令牌 c.JSON(http.StatusOK, gin.H{ "success": true, "message": "登录成功", "token": token, }) } // VerifyAuth 验证当前用户是否已登录 func VerifyAuth(c *gin.Context) { // 获取Authorization头 authHeader := c.GetHeader("Authorization") if authHeader == "" { c.JSON(http.StatusUnauthorized, gin.H{ "success": false, "message": "未授权", }) return } // 简单验证格式,实际项目中应该有完整的JWT验证 if len(authHeader) < 10 { c.JSON(http.StatusUnauthorized, gin.H{ "success": false, "message": "无效的令牌", }) return } // 成功响应 c.JSON(http.StatusOK, gin.H{ "success": true, "message": "已认证", }) }