fix: 修复多个安全缺陷和功能问题

- 移除加密相关代码(服务端和所有客户端)
- 修复 JWT 验证未检查签名算法的问题
- 修复重置密码使用不安全随机数的问题
- 实现 Logout 服务端失效机制
- 修复历史版本对比 diff 颜色标记错误
- 修复占位符解析循环引用风险
- 添加用户禁用状态检查
- 更新 bug 清单文档
This commit is contained in:
2026-03-10 21:07:22 +08:00
parent f41d53da41
commit 932db9fbdc
27 changed files with 292 additions and 721 deletions
+9
View File
@@ -1,10 +1,13 @@
package handler
import (
"kenaito-conf/server/internal/dao"
"kenaito-conf/server/internal/middleware"
"kenaito-conf/server/internal/model"
"kenaito-conf/server/internal/service"
"net/http"
"strconv"
"time"
"github.com/gin-gonic/gin"
)
@@ -51,5 +54,11 @@ func (h *AuthHandler) GetLoginUserInfo(c *gin.Context) {
}
func (h *AuthHandler) Logout(c *gin.Context) {
userInfo := middleware.GetUserInfo(c)
if userInfo != nil {
userId, _ := strconv.Atoi(userInfo.Id)
now := time.Now()
dao.Engine.ID(userId).Cols("last_logout_at").Update(&model.User{LastLogoutAt: &now})
}
c.JSON(http.StatusOK, model.WrapperResponse{Code: 0})
}
+2 -14
View File
@@ -13,13 +13,12 @@ import (
)
type ConfigHandler struct {
cryptoService *service.CryptoService
parseService *service.ConfigParseService
permService *service.PermissionService
}
func NewConfigHandler(crypto *service.CryptoService, parse *service.ConfigParseService, perm *service.PermissionService) *ConfigHandler {
return &ConfigHandler{cryptoService: crypto, parseService: parse, permService: perm}
func NewConfigHandler(parse *service.ConfigParseService, perm *service.PermissionService) *ConfigHandler {
return &ConfigHandler{parseService: parse, permService: perm}
}
type ConfigListRequest struct {
@@ -162,9 +161,6 @@ func (h *ConfigHandler) Add(c *gin.Context) {
}
}
// encrypt sensitive values
h.encryptIfRequired(&config)
if _, err := dao.Engine.Insert(&config); err != nil {
c.JSON(http.StatusOK, model.WrapperResponse{Code: 500, Msg: "保存失败"})
return
@@ -208,8 +204,6 @@ func (h *ConfigHandler) Update(c *gin.Context) {
now := time.Now()
config.UpdatedAt = &now
h.encryptIfRequired(&config)
dao.Engine.ID(config.Id).Cols("contents", "version", "updated_by", "updated_at").Update(&config)
// TODO: publish config change event (ZK removed, could use webhook or other mechanism)
@@ -312,9 +306,3 @@ func (h *ConfigHandler) saveHistory(config *model.AppConfig, operator string) {
}
dao.Engine.Insert(&history)
}
func (h *ConfigHandler) encryptIfRequired(config *model.AppConfig) {
// simplified: check if contents contain sensitive keys
// In production, parse the config and encrypt values with {Cipher} prefix
// For now, skip encryption logic
}
+2 -8
View File
@@ -13,12 +13,11 @@ import (
)
type ConfigApiHandler struct {
cryptoService *service.CryptoService
parseService *service.ConfigParseService
}
func NewConfigApiHandler(crypto *service.CryptoService, parse *service.ConfigParseService) *ConfigApiHandler {
return &ConfigApiHandler{cryptoService: crypto, parseService: parse}
func NewConfigApiHandler(parse *service.ConfigParseService) *ConfigApiHandler {
return &ConfigApiHandler{parseService: parse}
}
type FetchAllRequest struct {
@@ -104,11 +103,6 @@ func (h *ConfigApiHandler) FetchAllConfigs(c *gin.Context) {
return
}
// add encryption keys
globalCryptKey := h.cryptoService.GetCryptKey(0, req.Env)
result["kenaito.config.global-encrypt-secret"] = globalCryptKey
appCryptKey := h.cryptoService.GetCryptKey(app.Id, req.Env)
result["kenaito.config.encrypt-secret"] = appCryptKey
result["latest.fetch.timestamp"] = strconv.FormatInt(time.Now().UnixMilli(), 10)
c.JSON(http.StatusOK, result)
+3 -2
View File
@@ -6,7 +6,7 @@ import (
"kenaito-conf/server/internal/model"
"kenaito-conf/server/internal/service"
"kenaito-conf/server/internal/util"
"math/rand"
"crypto/rand"
"net/http"
"strconv"
"time"
@@ -341,8 +341,9 @@ func (h *UserHandler) Options(c *gin.Context) {
func randomString(n int) string {
const letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
b := make([]byte, n)
_, _ = rand.Read(b)
for i := range b {
b[i] = letters[rand.Intn(len(letters))]
b[i] = letters[int(b[i])%len(letters)]
}
return string(b)
}