feat: adjust deploy password and login limit

This commit is contained in:
engigu
2026-02-10 14:19:32 +08:00
parent 70a66c4693
commit b855400cec
6 changed files with 67 additions and 5 deletions
+1 -1
View File
@@ -6,6 +6,6 @@
启动后访问:http://localhost:8052
默认账号:`admin` / `123456`
默认账号:用户名 `admin`,密码见启动日志(首次启动随机生成)
+3 -2
View File
@@ -13,6 +13,7 @@
### 最近更新
**2026.02.11** - 增强安全性:首次启动使用随机密码并打印在日志中,登录接口增加防暴力破解,文件系统操作增加路径穿越锁定
**2026.02.10** - 重构任务调度系统,完善并发控制,优化文件树交互体验,支持任务执行实时日志流
**2026.02.06** - 整理 Docker 目录结构,增加 Alpine 及 Debian 13 (Trixie) 镜像支持
@@ -501,9 +502,9 @@ nginx -t && nginx -s reload
启动后访问:http://localhost:8052
**默认账号:** `admin` / `123456`
**默认账号:** 用户名 `admin`,密码见启动日志(首次启动会自动生成 12 位随机密码并打印在日志中)
> 首次登录后请立即修改默认密码
> **注意**:出于安全性考虑,系统不再使用固定默认密码。请在容器启动日志中搜索 `管理员账号创建成功` 找到您的随机密码,并登录后及时修改。
### 数据目录
+32
View File
@@ -2,6 +2,8 @@ package controllers
import (
"strconv"
"sync"
"time"
"github.com/engigu/baihu-panel/internal/constant"
"github.com/engigu/baihu-panel/internal/middleware"
@@ -17,6 +19,13 @@ type AuthController struct {
loginLogService *services.LoginLogService
}
type loginAttempt struct {
Count int
LastAttempt time.Time
}
var loginAttempts sync.Map
func NewAuthController(userService *services.UserService, settingsService *services.SettingsService, loginLogService *services.LoginLogService) *AuthController {
return &AuthController{
userService: userService,
@@ -39,14 +48,37 @@ func (ac *AuthController) Login(c *gin.Context) {
return
}
// 暴力破解防御
if val, ok := loginAttempts.Load(ip); ok {
attempt := val.(*loginAttempt)
if attempt.Count >= 5 && time.Since(attempt.LastAttempt) < time.Minute {
ac.loginLogService.Create(req.Username, ip, userAgent, "failed", "尝试次数过多,请一分钟后再试")
utils.TooManyRequests(c, "尝试次数过多,请一分钟后再试")
return
}
// 如果距离上次尝试已超过一分钟,重置计数
if time.Since(attempt.LastAttempt) >= time.Minute {
loginAttempts.Delete(ip)
}
}
user := ac.userService.GetUserByUsername(req.Username)
if user == nil || !ac.userService.ValidatePassword(user, req.Password) {
// 记录失败尝试
val, _ := loginAttempts.LoadOrStore(ip, &loginAttempt{Count: 0, LastAttempt: time.Now()})
attempt := val.(*loginAttempt)
attempt.Count++
attempt.LastAttempt = time.Now()
// 记录登录失败日志
ac.loginLogService.Create(req.Username, ip, userAgent, "failed", "用户名或密码错误")
utils.Unauthorized(c, "用户名或密码错误")
return
}
// 登录成功,清除尝试记录
loginAttempts.Delete(ip)
// 获取 cookie 过期天数
expireDays := 7
if days := ac.settingsService.Get(constant.SectionSite, constant.KeyCookieDays); days != "" {
+9 -2
View File
@@ -2,6 +2,7 @@ package services
import (
"github.com/engigu/baihu-panel/internal/logger"
"github.com/engigu/baihu-panel/internal/utils"
)
type InitService struct {
@@ -40,6 +41,12 @@ func (s *InitService) initializeAdmin(userService *UserService) {
return
}
userService.CreateUser("admin", "123456", "admin@local", "admin")
logger.Info("管理员账号创建成功: admin / 123456")
password := utils.RandomString(12)
userService.CreateUser("admin", password, "admin@local", "admin")
logger.Infof("--------------------------------------------------")
logger.Infof("管理员账号创建成功:")
logger.Infof("用户名: admin")
logger.Infof("密 码: %s", password)
logger.Infof("请妥善保管您的密码,并登录后及时修改。")
logger.Infof("--------------------------------------------------")
}
+18
View File
@@ -0,0 +1,18 @@
package utils
import (
"crypto/rand"
"math/big"
)
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
// RandomString 生成指定长度的随机字符串
func RandomString(n int) string {
b := make([]byte, n)
for i := range b {
num, _ := rand.Int(rand.Reader, big.NewInt(int64(len(charset))))
b[i] = charset[num.Int64()]
}
return string(b)
}
+4
View File
@@ -50,6 +50,10 @@ func NotFound(c *gin.Context, msg string) {
Error(c, 404, msg)
}
func TooManyRequests(c *gin.Context, msg string) {
Error(c, 429, msg)
}
func ServerError(c *gin.Context, msg string) {
Error(c, 500, msg)
}