Dapper 和 SQL 注入
Dapper and SQL injection
在我的例子中,我无法对过滤器等某些参数使用参数化查询,因为过滤器是一个长字符串(不是单个参数),所以我正在为此寻找解决方案。我的查询字符串中有以下代码片段。我试过放置“@filter”,但看起来 dapper 首先是原始查询字符串。
例如,我无法设置“....Column = @value”,因为我的列表的过滤器可能会发生变化,例如包含,开始于...
queryString = @"SELECT
R.RequestId As requestId,
R.Number AS number,
R.CargoReadyDate AS readyDate,
PL.Name AS portIdOfLoading,
PD.Name AS portIdOfDischarge,
R.Status AS status,
R.AllInFreightAmount_Value AS requestAmount ,
R.CreatedDate AS requestDate,
R.AllInFreightAmount_Currency as currency
FROM
Requests R
JOIN
[Ports] PL ON R.PortIdOfLoading = PL.PortId
JOIN
[Ports] PD ON R.PortIdOfDischarge = PD.PortId
WHERE
R.ShipperId = @accountId And " + statusFilter + filter + " " +
@"ORDER BY
R.CreatedDate DESC
OFFSET @pageSize * (@pageNumber - 1) ROWS
FETCH NEXT @pageSize ROWS ONLY ";
var data = _dapperService.QueryDataSet<RequestDto>(queryString,
new { accountId = query.AccountId, status = query.RequestStatus, pageSize = query.PageSize, pageNumber = query.PageNumber }, CommandType.Text);
return data;
最终,Dapper 无法帮助处理实际参数化步骤之外 发生的任何事情;如果你在 之前引入 SQL 个注入孔 将其交给 Dapper:是的,你将有 SQL 个注入孔。
不过,您仍然可以将 Dapper 用于重要的查询;你仍然可以参数化。例如,您可以这样做:
int? userId = /* something, could be null */
string region = /* something, could be null */
var sql = new StringBuilder(@"select ... /* whatever */ where Open = 1");
if (userId != null) sql.Append(" and UserId = @userId");
if (region != null) sql.Append(" and Region = @region");
// ... etc
var data = conn.Query<SomeType>(sql.ToString(), new { userId, region }).AsList();
在这里,Dapper 只会添加它实际看到的在查询中使用的参数;因此,如果 @userId
没有出现,则不会添加该参数。但至关重要的是:查询仍然是完全参数化的,并且没有 SQL 个注入孔。
对于更复杂的场景,Dapper 还支持类字典参数,对于需要按需添加参数而不是静态添加参数的地方。
在我的例子中,我无法对过滤器等某些参数使用参数化查询,因为过滤器是一个长字符串(不是单个参数),所以我正在为此寻找解决方案。我的查询字符串中有以下代码片段。我试过放置“@filter”,但看起来 dapper 首先是原始查询字符串。
例如,我无法设置“....Column = @value”,因为我的列表的过滤器可能会发生变化,例如包含,开始于...
queryString = @"SELECT
R.RequestId As requestId,
R.Number AS number,
R.CargoReadyDate AS readyDate,
PL.Name AS portIdOfLoading,
PD.Name AS portIdOfDischarge,
R.Status AS status,
R.AllInFreightAmount_Value AS requestAmount ,
R.CreatedDate AS requestDate,
R.AllInFreightAmount_Currency as currency
FROM
Requests R
JOIN
[Ports] PL ON R.PortIdOfLoading = PL.PortId
JOIN
[Ports] PD ON R.PortIdOfDischarge = PD.PortId
WHERE
R.ShipperId = @accountId And " + statusFilter + filter + " " +
@"ORDER BY
R.CreatedDate DESC
OFFSET @pageSize * (@pageNumber - 1) ROWS
FETCH NEXT @pageSize ROWS ONLY ";
var data = _dapperService.QueryDataSet<RequestDto>(queryString,
new { accountId = query.AccountId, status = query.RequestStatus, pageSize = query.PageSize, pageNumber = query.PageNumber }, CommandType.Text);
return data;
最终,Dapper 无法帮助处理实际参数化步骤之外 发生的任何事情;如果你在 之前引入 SQL 个注入孔 将其交给 Dapper:是的,你将有 SQL 个注入孔。
不过,您仍然可以将 Dapper 用于重要的查询;你仍然可以参数化。例如,您可以这样做:
int? userId = /* something, could be null */
string region = /* something, could be null */
var sql = new StringBuilder(@"select ... /* whatever */ where Open = 1");
if (userId != null) sql.Append(" and UserId = @userId");
if (region != null) sql.Append(" and Region = @region");
// ... etc
var data = conn.Query<SomeType>(sql.ToString(), new { userId, region }).AsList();
在这里,Dapper 只会添加它实际看到的在查询中使用的参数;因此,如果 @userId
没有出现,则不会添加该参数。但至关重要的是:查询仍然是完全参数化的,并且没有 SQL 个注入孔。
对于更复杂的场景,Dapper 还支持类字典参数,对于需要按需添加参数而不是静态添加参数的地方。