防SQL注入 生成参数化的通用分页查询语句
防SQL注入 生成参数化的通用分页查询语句
发布时间:2016-12-29 来源:查字典编辑
摘要:使用这种通用的存储过程进行分页查询,想要防SQL注入,只能对输入的参数进行过滤,例如将一个单引号“'”转换成两个单引号“''”,但这种做法是...

使用这种通用的存储过程进行分页查询,想要防SQL注入,只能对输入的参数进行过滤,例如将一个单引号“'”转换成两个单引号“''”,但这种做法是不安全的,厉害的黑客可以通过编码的方式绕过单引号的过滤,要想有效防SQL注入,只有参数化查询才是最终的解决方案。但问题就出在这种通用分页存储过程是在存储过程内部进行SQL语句拼接,根本无法修改为参数化的查询语句,因此这种通用分页存储过程是不可取的。但是如果不用通用的分页存储过程,则意味着必须为每个具体的分页查询写一个分页存储过程,这会增加不少的工作量。

经过几天的时间考虑之后,想到了一个用代码来生成参数化的通用分页查询语句的解决方案。代码如下:

复制代码 代码如下:

public class PagerQuery

{

private int _pageIndex;

private int _pageSize = 20;

private string _pk;

private string _fromClause;

private string _groupClause;

private string _selectClause;

private string _sortClause;

private StringBuilder _whereClause;

public DateTime DateFilter = DateTime.MinValue;

protected QueryBase()

{

_whereClause = new StringBuilder();

}

/**//// <summary>

/// 主键

/// </summary>

public string PK

{

get { return _pk; }

set { _pk = value; }

}

public string SelectClause

{

get { return _selectClause; }

set { _selectClause = value; }

}

public string FromClause

{

get { return _fromClause; }

set { _fromClause = value; }

}

public StringBuilder WhereClause

{

get { return _whereClause; }

set { _whereClause = value; }

}

public string GroupClause

{

get { return _groupClause; }

set { _groupClause = value; }

}

public string SortClause

{

get { return _sortClause; }

set { _sortClause = value; }

}

/**//// <summary>

/// 当前页数

/// </summary>

public int PageIndex

{

get { return _pageIndex; }

set { _pageIndex = value; }

}

/**//// <summary>

/// 分页大小

/// </summary>

public int PageSize

{

get { return _pageSize; }

set { _pageSize = value; }

}

/**//// <summary>

/// 生成缓存Key

/// </summary>

/// <returns></returns>

public override string GetCacheKey()

{

const string keyFormat = "Pager-SC:{0}-FC:{1}-WC:{2}-GC:{3}-SC:{4}";

return string.Format(keyFormat, SelectClause, FromClause, WhereClause, GroupClause, SortClause);

}

/**//// <summary>

/// 生成查询记录总数的SQL语句

/// </summary>

/// <returns></returns>

public string GenerateCountSql()

{

StringBuilder sb = new StringBuilder();

sb.AppendFormat(" from {0}", FromClause);

if (WhereClause.Length > 0)

sb.AppendFormat(" where 1=1 {0}", WhereClause);

if (!string.IsNullOrEmpty(GroupClause))

sb.AppendFormat(" group by {0}", GroupClause);

return string.Format("Select count(0) {0}", sb);

}

/**//// <summary>

/// 生成分页查询语句,包含记录总数

/// </summary>

/// <returns></returns>

public string GenerateSqlIncludeTotalRecords()

{

StringBuilder sb = new StringBuilder();

if (string.IsNullOrEmpty(SelectClause))

SelectClause = "*";

if (string.IsNullOrEmpty(SortClause))

SortClause = PK;

int start_row_num = (PageIndex - 1)*PageSize + 1;

sb.AppendFormat(" from {0}", FromClause);

if (WhereClause.Length > 0)

sb.AppendFormat(" where 1=1 {0}", WhereClause);

if (!string.IsNullOrEmpty(GroupClause))

sb.AppendFormat(" group by {0}", GroupClause);

string countSql = string.Format("Select count(0) {0};", sb);

string tempSql =

string.Format(

"WITH t AS (SELECT ROW_NUMBER() OVER(ORDER BY {0}) as row_number,{1}{2}) Select * from t where row_number BETWEEN {3} and {4};",

SortClause, SelectClause, sb, start_row_num, (start_row_num + PageSize - 1));

return tempSql + countSql;

}

/**//// <summary>

/// 生成分页查询语句

/// </summary>

/// <returns></returns>

public override string GenerateSql()

{

StringBuilder sb = new StringBuilder();

if (string.IsNullOrEmpty(SelectClause))

SelectClause = "*";

if (string.IsNullOrEmpty(SortClause))

SortClause = PK;

int start_row_num = (PageIndex - 1)*PageSize + 1;

sb.AppendFormat(" from {0}", FromClause);

if (WhereClause.Length > 0)

sb.AppendFormat(" where 1=1 {0}", WhereClause);

if (!string.IsNullOrEmpty(GroupClause))

sb.AppendFormat(" group by {0}", GroupClause);

return

string.Format(

"WITH t AS (SELECT ROW_NUMBER() OVER(ORDER BY {0}) as row_number,{1}{2}) Select * from t where row_number BETWEEN {3} and {4}",

SortClause, SelectClause, sb, start_row_num, (start_row_num + PageSize - 1));

}

}

使用方法:

复制代码 代码如下:

PagerQuery query = new PagerQuery();

query.PageIndex = 1;

query.PageSize = 20;

query.PK = "ID";

query.SelectClause = "*";

query.FromClause = "TestTable";

query.SortClause = "ID DESC";

if (!string.IsNullOrEmpty(code))

{

query.WhereClause.Append(" and ID= @ID");

}

a) GenerateCountSql ()方法生成的语句为:

Select count(0) from TestTable Where 1=1 and ID= @ID

b) GenerateSql()方法生成的语句为:

WITH t AS (SELECT ROW_NUMBER() OVER(ORDER BY ECID DESC) as row_number, * from TestTable where 1=1 and ID= @ID) Select * from t where row_number BETWEEN 1 and 20

c) GenerateSqlIncludetTotalRecords()方法生成的语句为:

WITH t AS (SELECT ROW_NUMBER() OVER(ORDER BY E.ECID DESC) as row_number,* from TestTable where 1=1 and ID= @ID) Select * from t where row_number BETWEEN 1 and 20;Select count(0) from ECBasicInfo where 1=1 and ID= @ID;

注意:以上代码生成的SQL语句是曾对SQL SERVER 2005以上版本的,希望这些代码对大家有用

推荐文章
猜你喜欢
附近的人在看
推荐阅读
拓展阅读
相关阅读
网友关注
最新asp.net教程学习
热门asp.net教程学习
编程开发子分类