|
|
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"` |
|
|
} |
|
|
|
|
|
|
|
|
type JWTClaims struct { |
|
|
Username string `json:"username"` |
|
|
Exp int64 `json:"exp"` |
|
|
Iat int64 `json:"iat"` |
|
|
Iss string `json:"iss"` |
|
|
} |
|
|
|
|
|
|
|
|
func generateToken(username string) (string, error) { |
|
|
|
|
|
nowTime := time.Now() |
|
|
expireTime := nowTime.Add(24 * time.Hour) |
|
|
|
|
|
claims := JWTClaims{ |
|
|
Username: username, |
|
|
Exp: expireTime.Unix(), |
|
|
Iat: nowTime.Unix(), |
|
|
Iss: "genspark2api", |
|
|
} |
|
|
|
|
|
|
|
|
claimsJSON, err := json.Marshal(claims) |
|
|
if err != nil { |
|
|
return "", err |
|
|
} |
|
|
|
|
|
|
|
|
payload := base64.RawURLEncoding.EncodeToString(claimsJSON) |
|
|
|
|
|
|
|
|
header := base64.RawURLEncoding.EncodeToString([]byte(`{"alg":"HS256","typ":"JWT"}`)) |
|
|
|
|
|
|
|
|
signatureInput := header + "." + payload |
|
|
|
|
|
|
|
|
h := sha256.New() |
|
|
h.Write([]byte(signatureInput + config.ApiSecret)) |
|
|
signature := base64.RawURLEncoding.EncodeToString(h.Sum(nil)) |
|
|
|
|
|
|
|
|
token := header + "." + payload + "." + signature |
|
|
|
|
|
return token, nil |
|
|
} |
|
|
|
|
|
|
|
|
func LoginPage(c *gin.Context) { |
|
|
c.File("./public/login.html") |
|
|
} |
|
|
|
|
|
|
|
|
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 |
|
|
} |
|
|
|
|
|
|
|
|
apiSecret := os.Getenv("API_SECRET") |
|
|
if apiSecret == "" { |
|
|
apiSecret = config.ApiSecret |
|
|
} |
|
|
|
|
|
|
|
|
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 |
|
|
} |
|
|
|
|
|
|
|
|
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, |
|
|
}) |
|
|
} |
|
|
|
|
|
|
|
|
func VerifyAuth(c *gin.Context) { |
|
|
|
|
|
authHeader := c.GetHeader("Authorization") |
|
|
if authHeader == "" { |
|
|
c.JSON(http.StatusUnauthorized, gin.H{ |
|
|
"success": false, |
|
|
"message": "未授权", |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
|
|
|
if len(authHeader) < 10 { |
|
|
c.JSON(http.StatusUnauthorized, gin.H{ |
|
|
"success": false, |
|
|
"message": "无效的令牌", |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
|
|
|
c.JSON(http.StatusOK, gin.H{ |
|
|
"success": true, |
|
|
"message": "已认证", |
|
|
}) |
|
|
} |
|
|
|