mirror of
https://github.com/skyle1995/NetworkAuth.git
synced 2026-05-25 02:24:05 +08:00
修修复 因为secure导致的登录失败问题
修复 安装拦截器部分情况下失效的问题
This commit is contained in:
@@ -71,6 +71,9 @@ func runServer(cmd *cobra.Command, args []string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if db != nil {
|
if db != nil {
|
||||||
|
// 检查系统是否已安装
|
||||||
|
isInstalled := services.GetSettingsService().GetString("is_installed", "0")
|
||||||
|
if isInstalled == "1" {
|
||||||
// 执行自动迁移(确保表结构存在)
|
// 执行自动迁移(确保表结构存在)
|
||||||
if err := database.AutoMigrate(); err != nil {
|
if err := database.AutoMigrate(); err != nil {
|
||||||
logrus.WithError(err).Fatal("数据库自动迁移失败")
|
logrus.WithError(err).Fatal("数据库自动迁移失败")
|
||||||
@@ -89,6 +92,9 @@ func runServer(cmd *cobra.Command, args []string) {
|
|||||||
|
|
||||||
// 启动日志清理定时任务
|
// 启动日志清理定时任务
|
||||||
services.StartLogCleanupTask()
|
services.StartLogCleanupTask()
|
||||||
|
} else {
|
||||||
|
logrus.Info("系统尚未安装 (is_installed=0),跳过核心组件初始化")
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
logrus.Info("系统处于未初始化状态,跳过数据库自动迁移和设置加载")
|
logrus.Info("系统处于未初始化状态,跳过数据库自动迁移和设置加载")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ func LoginHandler(c *gin.Context) {
|
|||||||
"avatar": user.Avatar,
|
"avatar": user.Avatar,
|
||||||
"nickname": user.Nickname,
|
"nickname": user.Nickname,
|
||||||
"username": user.Username,
|
"username": user.Username,
|
||||||
|
"token": token,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,9 +309,21 @@ func parseJWTToken(tokenString string) (*JWTClaims, error) {
|
|||||||
return nil, fmt.Errorf("invalid token")
|
return nil, fmt.Errorf("invalid token")
|
||||||
}
|
}
|
||||||
|
|
||||||
// getJWTCookie 获取JWT cookie的通用函数
|
// getJWTCookie 获取JWT cookie的通用函数,支持从Cookie或Authorization Header中获取
|
||||||
func getJWTCookie(c *gin.Context) (string, error) {
|
func getJWTCookie(c *gin.Context) (string, error) {
|
||||||
return c.Cookie("admin_session")
|
cookie, err := c.Cookie("admin_session")
|
||||||
|
if err == nil && cookie != "" {
|
||||||
|
return cookie, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果Cookie中没有,尝试从Authorization Header中获取 (兼容前端在非HTTPS环境下无法设置Secure Cookie的情况)
|
||||||
|
authHeader := c.GetHeader("Authorization")
|
||||||
|
if authHeader != "" && strings.HasPrefix(authHeader, "Bearer ") {
|
||||||
|
token := strings.TrimPrefix(authHeader, "Bearer ")
|
||||||
|
return token, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf("未找到会话信息")
|
||||||
}
|
}
|
||||||
|
|
||||||
// validateAdminPasswordHash 验证管理员密码哈希的通用函数
|
// validateAdminPasswordHash 验证管理员密码哈希的通用函数
|
||||||
@@ -367,13 +380,23 @@ func IsAdminAuthenticated(c *gin.Context) bool {
|
|||||||
// IsAdminAuthenticatedHttp 判断管理员是否已认证(HTTP兼容版本)
|
// IsAdminAuthenticatedHttp 判断管理员是否已认证(HTTP兼容版本)
|
||||||
// 保留此方法以兼容未迁移的 Handler
|
// 保留此方法以兼容未迁移的 Handler
|
||||||
func IsAdminAuthenticatedHttp(r *http.Request) bool {
|
func IsAdminAuthenticatedHttp(r *http.Request) bool {
|
||||||
|
token := ""
|
||||||
cookie, err := r.Cookie("admin_session")
|
cookie, err := r.Cookie("admin_session")
|
||||||
if err != nil || cookie.Value == "" {
|
if err == nil && cookie.Value != "" {
|
||||||
|
token = cookie.Value
|
||||||
|
} else {
|
||||||
|
authHeader := r.Header.Get("Authorization")
|
||||||
|
if authHeader != "" && strings.HasPrefix(authHeader, "Bearer ") {
|
||||||
|
token = strings.TrimPrefix(authHeader, "Bearer ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if token == "" {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解析并验证JWT令牌
|
// 解析并验证JWT令牌
|
||||||
claims, err := parseJWTToken(cookie.Value)
|
claims, err := parseJWTToken(token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -431,12 +454,22 @@ func IsAdminAuthenticatedWithCleanup(c *gin.Context) bool {
|
|||||||
|
|
||||||
// GetCurrentAdminUser 获取当前登录的管理员用户信息 (HTTP 兼容版)
|
// GetCurrentAdminUser 获取当前登录的管理员用户信息 (HTTP 兼容版)
|
||||||
func GetCurrentAdminUser(r *http.Request) (*JWTClaims, error) {
|
func GetCurrentAdminUser(r *http.Request) (*JWTClaims, error) {
|
||||||
|
token := ""
|
||||||
cookie, err := r.Cookie("admin_session")
|
cookie, err := r.Cookie("admin_session")
|
||||||
if err != nil {
|
if err == nil && cookie.Value != "" {
|
||||||
|
token = cookie.Value
|
||||||
|
} else {
|
||||||
|
authHeader := r.Header.Get("Authorization")
|
||||||
|
if authHeader != "" && strings.HasPrefix(authHeader, "Bearer ") {
|
||||||
|
token = strings.TrimPrefix(authHeader, "Bearer ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if token == "" {
|
||||||
return nil, fmt.Errorf("未找到会话信息")
|
return nil, fmt.Errorf("未找到会话信息")
|
||||||
}
|
}
|
||||||
|
|
||||||
claims, err := parseJWTToken(cookie.Value)
|
claims, err := parseJWTToken(token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("无效的会话信息")
|
return nil, fmt.Errorf("无效的会话信息")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
"gorm.io/driver/mysql"
|
"gorm.io/driver/mysql"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
@@ -165,5 +166,15 @@ func InstallSubmitHandler(c *gin.Context) {
|
|||||||
// 5. 更新内存缓存
|
// 5. 更新内存缓存
|
||||||
services.ResetSettingsService()
|
services.ResetSettingsService()
|
||||||
|
|
||||||
|
// 6. 动态初始化核心组件
|
||||||
|
// 在系统安装完成后,执行本来在 server.go 中需要已安装才能执行的初始化逻辑
|
||||||
|
encryptionKey := services.GetSettingsService().GetEncryptionKey()
|
||||||
|
if err := utils.InitEncryption(encryptionKey); err != nil {
|
||||||
|
logrus.WithError(err).Error("安装完成后加密管理器初始化失败")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 启动日志清理定时任务
|
||||||
|
services.StartLogCleanupTask()
|
||||||
|
|
||||||
c.JSON(http.StatusOK, gin.H{"code": 0, "msg": "安装成功"})
|
c.JSON(http.StatusOK, gin.H{"code": 0, "msg": "安装成功"})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,8 +116,8 @@ func SeedDefaultSettings() error {
|
|||||||
defaultSettings = append(defaultSettings, []models.Settings{
|
defaultSettings = append(defaultSettings, []models.Settings{
|
||||||
{
|
{
|
||||||
Name: "cookie_secure",
|
Name: "cookie_secure",
|
||||||
Value: "true",
|
Value: "false",
|
||||||
Description: "Cookie Secure属性(是否只在HTTPS下发送)",
|
Description: "是否启用安全Cookie(仅HTTPS),开启后HTTP访问可能导致登录失败",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "cookie_same_site",
|
Name: "cookie_same_site",
|
||||||
|
|||||||
@@ -3,10 +3,8 @@ package middleware
|
|||||||
import (
|
import (
|
||||||
"NetworkAuth/services"
|
"NetworkAuth/services"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/spf13/viper"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// InstallCheckMiddleware 检查系统是否已安装
|
// InstallCheckMiddleware 检查系统是否已安装
|
||||||
@@ -20,30 +18,6 @@ func InstallCheckMiddleware() gin.HandlerFunc {
|
|||||||
isInstalledStr := services.GetSettingsService().GetString("is_installed", "0")
|
isInstalledStr := services.GetSettingsService().GetString("is_installed", "0")
|
||||||
isInstalled := isInstalledStr == "1"
|
isInstalled := isInstalledStr == "1"
|
||||||
|
|
||||||
// 如果设置服务没获取到(因为未连接数据库),再结合文件判断
|
|
||||||
if !isInstalled {
|
|
||||||
// 检查数据库文件是否存在(如果是 sqlite)
|
|
||||||
dbType := viper.GetString("database.type")
|
|
||||||
switch dbType {
|
|
||||||
case "sqlite":
|
|
||||||
dbPath := viper.GetString("database.sqlite.path")
|
|
||||||
if dbPath == "" {
|
|
||||||
dbPath = "./database.db"
|
|
||||||
}
|
|
||||||
if _, err := os.Stat(dbPath); os.IsNotExist(err) {
|
|
||||||
isInstalled = false
|
|
||||||
} else {
|
|
||||||
isInstalled = true
|
|
||||||
}
|
|
||||||
case "mysql":
|
|
||||||
// 如果是 mysql 且配置了 database,我们认为是已安装
|
|
||||||
dbName := viper.GetString("database.mysql.database")
|
|
||||||
if dbName != "" {
|
|
||||||
isInstalled = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果未安装且是 API 请求但不是安装接口,则返回 403 JSON
|
// 如果未安装且是 API 请求但不是安装接口,则返回 403 JSON
|
||||||
// 如果是前端页面请求,不在此处拦截,交由前端 Vue Router 拦截并跳转至安装页
|
// 如果是前端页面请求,不在此处拦截,交由前端 Vue Router 拦截并跳转至安装页
|
||||||
if !isInstalled && !isInstallRoute && len(path) >= 4 && path[:4] == "/api" {
|
if !isInstalled && !isInstallRoute && len(path) >= 4 && path[:4] == "/api" {
|
||||||
|
|||||||
Reference in New Issue
Block a user