fix(sql): 修复SQL注入漏洞改用参数化查询
- app.go 将查询条件从字符串拼接改为占位符参数绑定 - config.go 将查询条件从字符串拼接改为占位符参数绑定 - user.go 将查询条件从字符串拼接改为占位符参数绑定 - 移除 app.go 中重复的条件构建逻辑 - 对 group_id、enabled 等参数增加类型校验与错误处理
This commit is contained in:
@@ -37,7 +37,9 @@ func (h *AppHandler) List(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
userInfo := middleware.GetUserInfo(c)
|
userInfo := middleware.GetUserInfo(c)
|
||||||
query := dao.Engine.Where("enabled = 1")
|
|
||||||
|
conditions := []string{"enabled = 1"}
|
||||||
|
args := make([]interface{}, 0, 6)
|
||||||
|
|
||||||
if !userInfo.IsSuperAdmin() {
|
if !userInfo.IsSuperAdmin() {
|
||||||
userId, _ := strconv.Atoi(userInfo.Id)
|
userId, _ := strconv.Atoi(userInfo.Id)
|
||||||
@@ -45,42 +47,41 @@ func (h *AppHandler) List(c *gin.Context) {
|
|||||||
|
|
||||||
if userInfo.IsGroupAdmin() && userInfo.GroupId != nil {
|
if userInfo.IsGroupAdmin() && userInfo.GroupId != nil {
|
||||||
// 组管理员:本组应用 + 自己是负责人的应用
|
// 组管理员:本组应用 + 自己是负责人的应用
|
||||||
query = query.And("(group_id = ? OR FIND_IN_SET('" + userIdStr + "', owner_ids) > 0)", *userInfo.GroupId)
|
conditions = append(conditions, "(group_id = ? OR FIND_IN_SET(?, owner_ids) > 0)")
|
||||||
|
args = append(args, *userInfo.GroupId, userIdStr)
|
||||||
} else {
|
} else {
|
||||||
// 普通用户:自己是负责人的应用
|
// 普通用户:自己是负责人的应用
|
||||||
query = query.And("FIND_IN_SET('" + userIdStr + "', owner_ids) > 0")
|
conditions = append(conditions, "FIND_IN_SET(?, owner_ids) > 0")
|
||||||
}
|
args = append(args, userIdStr)
|
||||||
}
|
|
||||||
|
|
||||||
var apps []model.Application
|
|
||||||
whereClause := "enabled = 1"
|
|
||||||
if !userInfo.IsSuperAdmin() {
|
|
||||||
userId, _ := strconv.Atoi(userInfo.Id)
|
|
||||||
userIdStr := strconv.Itoa(userId)
|
|
||||||
|
|
||||||
if userInfo.IsGroupAdmin() && userInfo.GroupId != nil {
|
|
||||||
// 组管理员:本组应用 + 自己是负责人的应用
|
|
||||||
whereClause += " AND (group_id = " + strconv.Itoa(*userInfo.GroupId) + " OR FIND_IN_SET('" + userIdStr + "', owner_ids) > 0)"
|
|
||||||
} else {
|
|
||||||
// 普通用户:自己是负责人的应用
|
|
||||||
whereClause += " AND (FIND_IN_SET('" + userIdStr + "', owner_ids) > 0)"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if req.AppType != "" {
|
if req.AppType != "" {
|
||||||
whereClause += " AND service_id = '" + req.AppType + "'"
|
conditions = append(conditions, "service_id = ?")
|
||||||
|
args = append(args, req.AppType)
|
||||||
}
|
}
|
||||||
if req.Name != "" {
|
if req.Name != "" {
|
||||||
whereClause += " AND name LIKE '%" + req.Name + "%'"
|
conditions = append(conditions, "name LIKE ?")
|
||||||
|
args = append(args, "%"+req.Name+"%")
|
||||||
}
|
}
|
||||||
if req.Code != "" {
|
if req.Code != "" {
|
||||||
whereClause += " AND code LIKE '%" + req.Code + "%'"
|
conditions = append(conditions, "code LIKE ?")
|
||||||
|
args = append(args, "%"+req.Code+"%")
|
||||||
}
|
}
|
||||||
if req.GroupId != "" {
|
if req.GroupId != "" {
|
||||||
whereClause += " AND group_id = " + req.GroupId
|
groupId, err := strconv.Atoi(req.GroupId)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, model.WrapperResponse{Code: 400, Msg: "参数错误"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
conditions = append(conditions, "group_id = ?")
|
||||||
|
args = append(args, groupId)
|
||||||
}
|
}
|
||||||
|
|
||||||
total, _ := dao.Engine.Where(whereClause).Count(&model.Application{})
|
whereClause := strings.Join(conditions, " AND ")
|
||||||
dao.Engine.Where(whereClause).Limit(req.PageSize, (req.PageNo-1)*req.PageSize).Find(&apps)
|
|
||||||
|
var apps []model.Application
|
||||||
|
total, _ := dao.Engine.Where(whereClause, args...).Count(&model.Application{})
|
||||||
|
dao.Engine.Where(whereClause, args...).Limit(req.PageSize, (req.PageNo-1)*req.PageSize).Find(&apps)
|
||||||
|
|
||||||
// load group names - batch query to avoid N+1
|
// load group names - batch query to avoid N+1
|
||||||
groupIds := make(map[int]bool)
|
groupIds := make(map[int]bool)
|
||||||
@@ -122,13 +123,13 @@ func (h *AppHandler) GetById(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type AddAppRequest struct {
|
type AddAppRequest struct {
|
||||||
Id int `json:"id"`
|
Id int `json:"id"`
|
||||||
GroupId *int `json:"groupId"`
|
GroupId *int `json:"groupId"`
|
||||||
Name string `json:"name" binding:"required"`
|
Name string `json:"name" binding:"required"`
|
||||||
Code string `json:"code" binding:"required"`
|
Code string `json:"code" binding:"required"`
|
||||||
ServiceId string `json:"serviceId"`
|
ServiceId string `json:"serviceId"`
|
||||||
OwnerIds []int `json:"ownerIds"`
|
OwnerIds []int `json:"ownerIds"`
|
||||||
Remarks string `json:"remarks"`
|
Remarks string `json:"remarks"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *AppHandler) Add(c *gin.Context) {
|
func (h *AppHandler) Add(c *gin.Context) {
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type ConfigHandler struct {
|
type ConfigHandler struct {
|
||||||
parseService *service.ConfigParseService
|
parseService *service.ConfigParseService
|
||||||
permService *service.PermissionService
|
permService *service.PermissionService
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConfigHandler(parse *service.ConfigParseService, perm *service.PermissionService) *ConfigHandler {
|
func NewConfigHandler(parse *service.ConfigParseService, perm *service.PermissionService) *ConfigHandler {
|
||||||
@@ -47,38 +47,38 @@ func (h *ConfigHandler) List(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 构建查询条件
|
// 构建查询条件
|
||||||
buildConditions := func() []string {
|
conditions := []string{"enabled = 1"}
|
||||||
conditions := []string{"enabled = 1"}
|
args := make([]interface{}, 0, 4)
|
||||||
if req.Env != "" {
|
if req.Env != "" {
|
||||||
conditions = append(conditions, "env = '"+req.Env+"'")
|
conditions = append(conditions, "env = ?")
|
||||||
|
args = append(args, req.Env)
|
||||||
|
}
|
||||||
|
if req.AppId != nil {
|
||||||
|
if *req.AppId <= 0 {
|
||||||
|
conditions = append(conditions, "(app_id is null OR app_id = 0)")
|
||||||
|
} else {
|
||||||
|
conditions = append(conditions, "app_id = ?")
|
||||||
|
args = append(args, *req.AppId)
|
||||||
}
|
}
|
||||||
if req.AppId != nil {
|
}
|
||||||
if *req.AppId <= 0 {
|
if !userInfo.IsSuperAdmin() {
|
||||||
conditions = append(conditions, "(app_id is null OR app_id = 0)")
|
if userInfo.IsGroupAdmin() && userInfo.GroupId != nil {
|
||||||
} else {
|
conditions = append(conditions, "group_id = ?")
|
||||||
conditions = append(conditions, "app_id = "+strconv.Itoa(*req.AppId))
|
args = append(args, *userInfo.GroupId)
|
||||||
|
} else if len(userInfo.GrantAppIds) > 0 {
|
||||||
|
ids := make([]string, len(userInfo.GrantAppIds))
|
||||||
|
for i, id := range userInfo.GrantAppIds {
|
||||||
|
ids[i] = strconv.Itoa(id)
|
||||||
}
|
}
|
||||||
|
conditions = append(conditions, "app_id in ("+strings.Join(ids, ",")+")")
|
||||||
}
|
}
|
||||||
if !userInfo.IsSuperAdmin() {
|
|
||||||
if userInfo.IsGroupAdmin() && userInfo.GroupId != nil {
|
|
||||||
conditions = append(conditions, "group_id = "+strconv.Itoa(*userInfo.GroupId))
|
|
||||||
} else if len(userInfo.GrantAppIds) > 0 {
|
|
||||||
ids := make([]string, len(userInfo.GrantAppIds))
|
|
||||||
for i, id := range userInfo.GrantAppIds {
|
|
||||||
ids[i] = strconv.Itoa(id)
|
|
||||||
}
|
|
||||||
conditions = append(conditions, "app_id in ("+strings.Join(ids, ",")+")")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return conditions
|
|
||||||
}
|
}
|
||||||
|
|
||||||
conditions := buildConditions()
|
|
||||||
whereClause := strings.Join(conditions, " AND ")
|
whereClause := strings.Join(conditions, " AND ")
|
||||||
|
|
||||||
var configs []model.AppConfig
|
var configs []model.AppConfig
|
||||||
total, _ := dao.Engine.Where(whereClause).Count(&model.AppConfig{})
|
total, _ := dao.Engine.Where(whereClause, args...).Count(&model.AppConfig{})
|
||||||
dao.Engine.Where(whereClause).Limit(req.PageSize, (req.PageNo-1)*req.PageSize).Find(&configs)
|
dao.Engine.Where(whereClause, args...).Limit(req.PageSize, (req.PageNo-1)*req.PageSize).Find(&configs)
|
||||||
|
|
||||||
// build app names (batch query) and collect configIds for client counts
|
// build app names (batch query) and collect configIds for client counts
|
||||||
configIds := make([]int, 0, len(configs))
|
configIds := make([]int, 0, len(configs))
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package handler
|
package handler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/rand"
|
||||||
"kenaito-conf/server/internal/dao"
|
"kenaito-conf/server/internal/dao"
|
||||||
"kenaito-conf/server/internal/middleware"
|
"kenaito-conf/server/internal/middleware"
|
||||||
"kenaito-conf/server/internal/model"
|
"kenaito-conf/server/internal/model"
|
||||||
"kenaito-conf/server/internal/service"
|
"kenaito-conf/server/internal/service"
|
||||||
"kenaito-conf/server/internal/util"
|
"kenaito-conf/server/internal/util"
|
||||||
"crypto/rand"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -30,30 +30,48 @@ func (h *UserHandler) List(c *gin.Context) {
|
|||||||
enabledStr := c.Query("enabled")
|
enabledStr := c.Query("enabled")
|
||||||
userInfo := middleware.GetUserInfo(c)
|
userInfo := middleware.GetUserInfo(c)
|
||||||
|
|
||||||
buildConditions := func() []string {
|
buildConditions := func() (string, []interface{}) {
|
||||||
conditions := []string{"1=1"}
|
conditions := []string{"1=1"}
|
||||||
|
args := make([]interface{}, 0, 4)
|
||||||
if !userInfo.IsSuperAdmin() && userInfo.GroupId != nil {
|
if !userInfo.IsSuperAdmin() && userInfo.GroupId != nil {
|
||||||
conditions = append(conditions, "group_id = "+strconv.Itoa(*userInfo.GroupId))
|
conditions = append(conditions, "group_id = ?")
|
||||||
|
args = append(args, *userInfo.GroupId)
|
||||||
}
|
}
|
||||||
if groupIdStr != "" {
|
if groupIdStr != "" {
|
||||||
conditions = append(conditions, "group_id = "+groupIdStr)
|
groupId, err := strconv.Atoi(groupIdStr)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
conditions = append(conditions, "group_id = ?")
|
||||||
|
args = append(args, groupId)
|
||||||
}
|
}
|
||||||
if name != "" {
|
if name != "" {
|
||||||
conditions = append(conditions, "name like '%"+name+"%'")
|
conditions = append(conditions, "name LIKE ?")
|
||||||
|
args = append(args, "%"+name+"%")
|
||||||
}
|
}
|
||||||
if userType != "" {
|
if userType != "" {
|
||||||
conditions = append(conditions, "type = '"+userType+"'")
|
conditions = append(conditions, "type = ?")
|
||||||
|
args = append(args, userType)
|
||||||
}
|
}
|
||||||
if enabledStr != "" {
|
if enabledStr != "" {
|
||||||
conditions = append(conditions, "enabled = "+enabledStr)
|
enabled, err := strconv.Atoi(enabledStr)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
conditions = append(conditions, "enabled = ?")
|
||||||
|
args = append(args, enabled)
|
||||||
}
|
}
|
||||||
return conditions
|
return strings.Join(conditions, " AND "), args
|
||||||
}
|
}
|
||||||
|
|
||||||
whereClause := strings.Join(buildConditions(), " AND ")
|
whereClause, args := buildConditions()
|
||||||
|
if whereClause == "" {
|
||||||
|
c.JSON(http.StatusBadRequest, model.WrapperResponse{Code: 400, Msg: "参数错误"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var users []model.User
|
var users []model.User
|
||||||
dao.Engine.Where(whereClause).Find(&users)
|
dao.Engine.Where(whereClause, args...).Find(&users)
|
||||||
|
|
||||||
// load group names
|
// load group names
|
||||||
var groups []model.BusinessGroup
|
var groups []model.BusinessGroup
|
||||||
|
|||||||
Reference in New Issue
Block a user