提问人:jen 提问时间:9/8/2022 更新时间:9/10/2022 访问量:978
在哪里验证输入参数以防止 C# Web API 控制器或服务或存储库中的 SQL 注入?
Where to validate input parameters to prevent SQL injection in C# web API controller or service or repository?
问:
我知道参数化查询足以防止 SQL 注入。验证输入参数是否也是好的做法?验证输入参数的好方法是什么,以及在哪里(控制器、服务、存储库)验证它们?
这是我的控制器方法:
public async Task<ActionResult<List<Level>>> GetLevelsAsync([FromRoute] string Code, string Year)
{
int appId = IsoCode.FromName(Code).Id;
var result = await _sampleService.GetLevelsAsync(appId, Year);
return result;
}
这是我的服务方法:
public async Task<List<Level>> GetLevelsAsync(int appId, string year)
{
if (string.IsNullOrWhiteSpace(year) == true)
throw new ArgumentNullException(nameof(year));
var result = await _sampleRepository.GetLevelsByYear(appId, year);
return result;
}
这是我的存储库方法:
public async Task<List<Level>> GetLevelsByYear(int appId, string year)
{
if (string.IsNullOrWhiteSpace(year))
throw new ArgumentNullException(nameof(year));
var result = new List<Level>();
var parameters = new { AppId = appId, Year = year };
string sql = @"
SELECT *
FROM [Levels] as l, [LevelYears] as v
WHERE
v.LevelId = l.Id AND l.Active = 1 AND l.AppId = @AppId AND v.Year = @Year
ORDER BY v.Sort asc
";
using (IDbConnection db = new SqlConnection(_settings.SqlServerConnString))
{
try
{
result = db.Query<Level>(sql, parameters).ToList();
}
catch (Exception e)
{
_logger.LogError(e, "Error querying levels by year", new { appId, year });
throw;
}
}
return result;
}
答:
4赞
Egret
9/10/2022
#1
验证是很好的防御性编码。一些开发人员(我敢肯定不是你)将数据库中的数据视为“可信数据”,并且没有正确利用编码或预处理语句,这可能导致后续问题,例如二阶 SQL 注入、存储的 XSS,甚至业务逻辑问题。
验证取决于上下文。正面验证(白名单验证)是最佳做法,但并非总是可行。一些例子:
- 您通常可以检查特定值是否为一组已知值之一(白名单验证)
- 如果字段应该是整数或日期,则可以验证此字段以确保它包含该数据类型(或者可能为 NULL)。
- 您可以要求大多数字段具有最小和最大长度。
- 应验证任何字符串是否仅包含有效的 字符进行编码(例如,没有无效的 UTF-8 序列,只有可打印的字符)——这通常可以在 WAF 或 servlet 过滤器中更普遍地完成
在哪里验证?当数据通过信任边界时,应始终进行验证 - 验证来自其他源的任何数据。验证应位于可能重用的层。在这种情况下,我建议在这种情况下在服务级别进行验证。
评论
FluentValidation