Fix Services & Update the middleware && others
This commit is contained in:
@@ -1,43 +1,118 @@
|
||||
// Filename: internal/webhandlers/auth_handler.go (最终现代化改造版)
|
||||
// Filename: internal/webhandlers/auth_handler.go
|
||||
|
||||
package webhandlers
|
||||
|
||||
import (
|
||||
"gemini-balancer/internal/middleware"
|
||||
"gemini-balancer/internal/service" // [核心改造] 依赖service层
|
||||
"gemini-balancer/internal/service"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// WebAuthHandler [核心改造] 依赖关系净化,注入SecurityService
|
||||
// WebAuthHandler Web 认证处理器
|
||||
type WebAuthHandler struct {
|
||||
securityService *service.SecurityService
|
||||
logger *logrus.Logger
|
||||
}
|
||||
|
||||
// NewWebAuthHandler [核心改造] 构造函数更新
|
||||
// NewWebAuthHandler 创建 WebAuthHandler
|
||||
func NewWebAuthHandler(securityService *service.SecurityService) *WebAuthHandler {
|
||||
logger := logrus.New()
|
||||
logger.SetLevel(logrus.InfoLevel)
|
||||
|
||||
return &WebAuthHandler{
|
||||
securityService: securityService,
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
// ShowLoginPage 保持不变
|
||||
// ShowLoginPage 显示登录页面
|
||||
func (h *WebAuthHandler) ShowLoginPage(c *gin.Context) {
|
||||
errMsg := c.Query("error")
|
||||
from := c.Query("from") // 可以从登录失败的页面返回
|
||||
|
||||
// 验证重定向路径(防止开放重定向攻击)
|
||||
redirectPath := h.validateRedirectPath(c.Query("redirect"))
|
||||
|
||||
// 如果已登录,直接重定向
|
||||
if cookie := middleware.ExtractTokenFromCookie(c); cookie != "" {
|
||||
if _, err := h.securityService.AuthenticateToken(cookie); err == nil {
|
||||
c.Redirect(http.StatusFound, redirectPath)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
c.HTML(http.StatusOK, "auth.html", gin.H{
|
||||
"error": errMsg,
|
||||
"from": from,
|
||||
"error": errMsg,
|
||||
"redirect": redirectPath,
|
||||
})
|
||||
}
|
||||
|
||||
// HandleLogin [核心改造] 认证逻辑完全委托给SecurityService
|
||||
// HandleLogin 已废弃(项目无用户名系统)
|
||||
func (h *WebAuthHandler) HandleLogin(c *gin.Context) {
|
||||
c.Redirect(http.StatusFound, "/login?error=DEPRECATED_LOGIN_METHOD")
|
||||
}
|
||||
|
||||
// HandleLogout 保持不变
|
||||
// HandleLogout 处理登出请求
|
||||
func (h *WebAuthHandler) HandleLogout(c *gin.Context) {
|
||||
cookie := middleware.ExtractTokenFromCookie(c)
|
||||
|
||||
if cookie != "" {
|
||||
// 尝试获取 Token 信息用于日志
|
||||
authToken, err := h.securityService.AuthenticateToken(cookie)
|
||||
if err == nil {
|
||||
h.logger.WithFields(logrus.Fields{
|
||||
"token_id": authToken.ID,
|
||||
"client_ip": c.ClientIP(),
|
||||
}).Info("User logged out")
|
||||
} else {
|
||||
h.logger.WithField("client_ip", c.ClientIP()).Warn("Logout with invalid token")
|
||||
}
|
||||
|
||||
// 使缓存失效
|
||||
middleware.InvalidateTokenCache(cookie)
|
||||
} else {
|
||||
h.logger.WithField("client_ip", c.ClientIP()).Debug("Logout without session cookie")
|
||||
}
|
||||
|
||||
// 清除 Cookie
|
||||
middleware.ClearAdminSessionCookie(c)
|
||||
|
||||
// 重定向到登录页
|
||||
c.Redirect(http.StatusFound, "/login")
|
||||
}
|
||||
|
||||
// validateRedirectPath 验证重定向路径(防止开放重定向攻击)
|
||||
func (h *WebAuthHandler) validateRedirectPath(path string) string {
|
||||
defaultPath := "/dashboard"
|
||||
|
||||
if path == "" {
|
||||
return defaultPath
|
||||
}
|
||||
|
||||
// 只允许内部路径
|
||||
if !strings.HasPrefix(path, "/") || strings.HasPrefix(path, "//") {
|
||||
h.logger.WithField("path", path).Warn("Invalid redirect path blocked")
|
||||
return defaultPath
|
||||
}
|
||||
|
||||
// 白名单验证
|
||||
allowedPaths := []string{
|
||||
"/dashboard",
|
||||
"/keys",
|
||||
"/settings",
|
||||
"/logs",
|
||||
"/tasks",
|
||||
"/chat",
|
||||
}
|
||||
|
||||
for _, allowed := range allowedPaths {
|
||||
if strings.HasPrefix(path, allowed) {
|
||||
return path
|
||||
}
|
||||
}
|
||||
|
||||
return defaultPath
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user