防SQL注入生成参数化的通用分页查询语句
2023-06-13 09:14:23 时间
使用这种通用的存储过程进行分页查询,想要防SQL注入,只能对输入的参数进行过滤,例如将一个单引号“"”转换成两个单引号“""”,但这种做法是不安全的,厉害的黑客可以通过编码的方式绕过单引号的过滤,要想有效防SQL注入,只有参数化查询才是最终的解决方案。但问题就出在这种通用分页存储过程是在存储过程内部进行SQL语句拼接,根本无法修改为参数化的查询语句,因此这种通用分页存储过程是不可取的。但是如果不用通用的分页存储过程,则意味着必须为每个具体的分页查询写一个分页存储过程,这会增加不少的工作量。
经过几天的时间考虑之后,想到了一个用代码来生成参数化的通用分页查询语句的解决方案。代码如下:
复制代码代码如下:
经过几天的时间考虑之后,想到了一个用代码来生成参数化的通用分页查询语句的解决方案。代码如下:
publicclassPagerQuery
{
privateint_pageIndex;
privateint_pageSize=20;
privatestring_pk;
privatestring_fromClause;
privatestring_groupClause;
privatestring_selectClause;
privatestring_sortClause;
privateStringBuilder_whereClause;
publicDateTimeDateFilter=DateTime.MinValue;
protectedQueryBase()
{
_whereClause=newStringBuilder();
}
/**////<summary>
///主键
///</summary>
publicstringPK
{
get{return_pk;}
set{_pk=value;}
}
publicstringSelectClause
{
get{return_selectClause;}
set{_selectClause=value;}
}
publicstringFromClause
{
get{return_fromClause;}
set{_fromClause=value;}
}
publicStringBuilderWhereClause
{
get{return_whereClause;}
set{_whereClause=value;}
}
publicstringGroupClause
{
get{return_groupClause;}
set{_groupClause=value;}
}
publicstringSortClause
{
get{return_sortClause;}
set{_sortClause=value;}
}
/**////<summary>
///当前页数
///</summary>
publicintPageIndex
{
get{return_pageIndex;}
set{_pageIndex=value;}
}
/**////<summary>
///分页大小
///</summary>
publicintPageSize
{
get{return_pageSize;}
set{_pageSize=value;}
}
/**////<summary>
///生成缓存Key
///</summary>
///<returns></returns>
publicoverridestringGetCacheKey()
{
conststringkeyFormat="Pager-SC:{0}-FC:{1}-WC:{2}-GC:{3}-SC:{4}";
returnstring.Format(keyFormat,SelectClause,FromClause,WhereClause,GroupClause,SortClause);
}
/**////<summary>
///生成查询记录总数的SQL语句
///</summary>
///<returns></returns>
publicstringGenerateCountSql()
{
StringBuildersb=newStringBuilder();
sb.AppendFormat("from{0}",FromClause);
if(WhereClause.Length>0)
sb.AppendFormat("where1=1{0}",WhereClause);
if(!string.IsNullOrEmpty(GroupClause))
sb.AppendFormat("groupby{0}",GroupClause);
returnstring.Format("Selectcount(0){0}",sb);
}
/**////<summary>
///生成分页查询语句,包含记录总数
///</summary>
///<returns></returns>
publicstringGenerateSqlIncludeTotalRecords()
{
StringBuildersb=newStringBuilder();
if(string.IsNullOrEmpty(SelectClause))
SelectClause="*";
if(string.IsNullOrEmpty(SortClause))
SortClause=PK;
intstart_row_num=(PageIndex-1)*PageSize+1;
sb.AppendFormat("from{0}",FromClause);
if(WhereClause.Length>0)
sb.AppendFormat("where1=1{0}",WhereClause);
if(!string.IsNullOrEmpty(GroupClause))
sb.AppendFormat("groupby{0}",GroupClause);
stringcountSql=string.Format("Selectcount(0){0};",sb);
stringtempSql=
string.Format(
"WITHtAS(SELECTROW_NUMBER()OVER(ORDERBY{0})asrow_number,{1}{2})Select*fromtwhererow_numberBETWEEN{3}and{4};",
SortClause,SelectClause,sb,start_row_num,(start_row_num+PageSize-1));
returntempSql+countSql;
}
/**////<summary>
///生成分页查询语句
///</summary>
///<returns></returns>
publicoverridestringGenerateSql()
{
StringBuildersb=newStringBuilder();
if(string.IsNullOrEmpty(SelectClause))
SelectClause="*";
if(string.IsNullOrEmpty(SortClause))
SortClause=PK;
intstart_row_num=(PageIndex-1)*PageSize+1;
sb.AppendFormat("from{0}",FromClause);
if(WhereClause.Length>0)
sb.AppendFormat("where1=1{0}",WhereClause);
if(!string.IsNullOrEmpty(GroupClause))
sb.AppendFormat("groupby{0}",GroupClause);
return
string.Format(
"WITHtAS(SELECTROW_NUMBER()OVER(ORDERBY{0})asrow_number,{1}{2})Select*fromtwhererow_numberBETWEEN{3}and{4}",
SortClause,SelectClause,sb,start_row_num,(start_row_num+PageSize-1));
}
}
使用方法:
PagerQueryquery=newPagerQuery();
query.PageIndex=1;
query.PageSize=20;
query.PK="ID";
query.SelectClause="*";
query.FromClause="TestTable";
query.SortClause="IDDESC";
if(!string.IsNullOrEmpty(code))
{
query.WhereClause.Append("andID=@ID");
}
a)GenerateCountSql()方法生成的语句为:
Selectcount(0)fromTestTableWhere1=1andID=@ID
b)GenerateSql()方法生成的语句为:
WITHtAS(SELECTROW_NUMBER()OVER(ORDERBYECIDDESC)asrow_number,*fromTestTablewhere1=1andID=@ID)Select*fromtwhererow_numberBETWEEN1and20
c)GenerateSqlIncludetTotalRecords()方法生成的语句为:
WITHtAS(SELECTROW_NUMBER()OVER(ORDERBYE.ECIDDESC)asrow_number,*fromTestTablewhere1=1andID=@ID)Select*fromtwhererow_numberBETWEEN1and20;Selectcount(0)fromECBasicInfowhere1=1andID=@ID;
注意:以上代码生成的SQL语句是曾对SQLSERVER2005以上版本的,希望这些代码对大家有用
相关文章
- SQL注入之联合查询注入
- 1.sql注入基础
- 2023-01-03:超过5名学生的课。编写一个SQL查询来报告 至少有5个学生 的所有班级,返回结果不限顺序。请问sql语句如何写? +---------+
- SQL开发知识:Sql注入原理简介
- SQL开发知识:Oracle查询sql语句错误信息的控制和定位处理方式
- SQL开发知识:关于表oracle的一些特殊查询sql语句
- Spring的三种注入方式(Setter、构造函数和自动注入)详解编程语言
- 快速掌握Oracle的创建表SQL语句(oracle创建表sql)
- SQL与Oracle:比较与实现(sql与oracle)
- 文件MySQL导入SQL文件教程(mysql怎么导入sql)
- MSSQL实现SQL注入防护的完美解决方案(mssql 防sql注入)
- Oracle SQL跟踪工具:优化SQL查询的得力助手(oracle跟踪sql工具)
- MySQL实现SQL脚本查询与操作(mysql执行sql脚本)
- Oracle查询:锁定表的SQL语句(oracle查询锁表sql)
- 探索Oracle数据库中的关联式SQL(oracle关联sql)
- MySQL操作如何使用SQL窗口进行数据查询和修改(mysql 中sql窗口)
- 优化深入探究Oracle下的SQL优化之道(oracle下sql)
- 使用Oracle SQL处理文本数据的方法(oracle sql文本)
- Oracle SQL解锁数据库的最强利器(oracle sql文)
- 用Oracle SQL开心一整天(oracle sql搞笑)
- SQL数据库的高级sql注入的一些知识
- sql查询本年、本月、本日记录的语句,附SQL日期函数
- SQLServer中用T—SQL命令查询一个数据库中有哪些表的sql语句
- php中防止SQL注入的最佳解决方法
- PHP登录环节防止sql注入的方法浅析