timigogo's picture
Upload 63 files
fe3856c verified
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": "已认证",
})
}