Go语言代码:分页查询服务实现 - 安全与性能优化
这段代码实现了 Go 语言中的分页查询功能,用于获取帖子列表。虽然功能实现基本正确,但存在一些潜在的安全和性能问题。
-
错误信息不够明确: 当传入的参数不合法时,返回的错误信息过于笼统,难以帮助调用者快速定位问题。建议提供更详细的错误信息,例如具体哪个参数不合法,以及原因。
-
SQL 注入风险: 在处理关键词参数时,使用了
Like查询,没有对postQuery.Keyword进行转义处理,可能会导致 SQL 注入攻击。建议使用预编译语句或参数化查询来避免此问题。 -
密码参数处理不当: 使用
Neq查询可能导致查询结果不准确,因为Neq查询不区分大小写。建议使用NotEq或Ne来确保查询结果的准确性。 -
类型转换错误风险: 将状态值转换为
driver.Valuer类型可能会导致类型转换错误,建议使用更安全的方式进行类型转换。 -
性能问题: 使用
Join查询可能会影响性能,尤其是当数据量较大时。建议根据实际情况考虑使用其他更优化的查询方式,例如使用子查询或索引。同时,代码中没有对分类 ID 进行验证,可能会出现无效的分类 ID 导致查询结果不准确的情况。
优化建议:
- 改进错误信息,提供更详细的错误描述。
- 使用预编译语句或参数化查询来防止 SQL 注入。
- 使用更安全的类型转换方式。
- 根据实际情况优化查询方式,例如使用子查询或索引。
- 对分类 ID 进行验证,确保其有效性。
示例代码:
func (p postServiceImpl) Page(ctx context.Context, postQuery param.PostQuery) ([]*entity.Post, int64, error) {
// 1. 验证分页参数
if postQuery.PageNum < 0 || postQuery.PageSize <= 0 {
return nil, 0, xerr.BadParam.New("Invalid paging parameters").WithStatus(xerr.StatusBadRequest)
}
// 2. 获取数据库连接
postDAL := dal.GetQueryByCtx(ctx).Post
postCategoryDAL := dal.GetQueryByCtx(ctx).PostCategory
// 3. 创建查询语句
postDo := postDAL.WithContext(ctx).Debug().Where(postDAL.Type.Eq(consts.PostTypePost))
// 4. 处理排序参数
err := BuildSort(postQuery.Sort, &postDAL, &postDo)
if err != nil {
return nil, 0, err
}
// 5. 处理关键词参数
if postQuery.Keyword != nil {
// 使用预编译语句或参数化查询
postDo.Where(postDAL.Title.Like(fmt.Sprintf("%%' + *postQuery.Keyword + '%%"))).Or(postDAL.OriginalContent.Like(fmt.Sprintf("%%' + *postQuery.Keyword + '%%")))
}
// 6. 处理密码参数
if postQuery.WithPassword != nil && !*postQuery.WithPassword {
// 使用 NotEq 查询
postDo.Where(postDAL.Password.Ne(``))
}
// 7. 处理状态参数
if len(postQuery.Statuses) > 0 {
// 使用更安全的类型转换方式
statuesValue := make([]interface{}, len(postQuery.Statuses))
for i, status := range postQuery.Statuses {
statuesValue[i] = status
}
postDo = postDo.Where(postDAL.Status.In(statuesValue...))
}
// 8. 处理分类 ID 参数
if postQuery.CategoryID != nil {
// 验证分类 ID
if !isValidCategoryID(*postQuery.CategoryID) {
return nil, 0, xerr.BadParam.New("Invalid category ID").WithStatus(xerr.StatusBadRequest)
}
// 使用子查询或索引优化查询
postDo.Where(postDAL.CategoryID.Eq(*postQuery.CategoryID))
}
// 9. 执行查询
posts, totalCount, err := postDo.FindByPage(postQuery.PageNum*postQuery.PageSize, postQuery.PageSize)
if err != nil {
return nil, 0, WrapDBErr(err)
}
// 10. 返回结果
return posts, totalCount, nil
}
这段示例代码只是针对部分问题进行了修改,具体的优化方案还需要根据实际情况进行调整。
原文地址: https://www.cveoy.top/t/topic/nPrU 著作权归作者所有。请勿转载和采集!