防SQL注入:生成参数化的通用分页查询语句

简介: http://www.cnblogs.com/NickYao/archive/2008/11/28/1343229.html      前些时间看了玉开兄的“如此高效通用的分页存储过程是带有sql注入漏洞的”这篇文章,才突然想起某个项目也是使用了累似的通用分页存储过程。

http://www.cnblogs.com/NickYao/archive/2008/11/28/1343229.html


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

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

img_1c53668bcee393edac0d7b3b3daff1ae.gif img_405b18b4b6584ae338e0f6ecaf736533.gif Code
    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以上版本的,希望这些代码对大家有用

目录
相关文章
|
9月前
|
SQL 安全 数据库
如何在Django中正确使用参数化查询或ORM来避免SQL注入漏洞?
如何在Django中正确使用参数化查询或ORM来避免SQL注入漏洞?
518 77
|
9月前
|
SQL Java 数据库连接
如何在 Java 代码中使用 JSqlParser 解析复杂的 SQL 语句?
大家好,我是 V 哥。JSqlParser 是一个用于解析 SQL 语句的 Java 库,可将 SQL 解析为 Java 对象树,支持多种 SQL 类型(如 `SELECT`、`INSERT` 等)。它适用于 SQL 分析、修改、生成和验证等场景。通过 Maven 或 Gradle 安装后,可以方便地在 Java 代码中使用。
2669 11
|
11月前
|
SQL 安全 PHP
PHP开发中防止SQL注入的方法,包括使用参数化查询、对用户输入进行过滤和验证、使用安全的框架和库等,旨在帮助开发者有效应对SQL注入这一常见安全威胁,保障应用安全
本文深入探讨了PHP开发中防止SQL注入的方法,包括使用参数化查询、对用户输入进行过滤和验证、使用安全的框架和库等,旨在帮助开发者有效应对SQL注入这一常见安全威胁,保障应用安全。
428 4
|
11月前
|
SQL 安全 前端开发
Web学习_SQL注入_联合查询注入
联合查询注入是一种强大的SQL注入攻击方式,攻击者可以通过 `UNION`语句合并多个查询的结果,从而获取敏感信息。防御SQL注入需要多层次的措施,包括使用预处理语句和参数化查询、输入验证和过滤、最小权限原则、隐藏错误信息以及使用Web应用防火墙。通过这些措施,可以有效地提高Web应用程序的安全性,防止SQL注入攻击。
337 2
|
12月前
|
SQL Java 数据库连接
如何使用`DriverManager.getConnection()`连接数据库,并利用`PreparedStatement`执行参数化查询,有效防止SQL注入。
【10月更文挑战第6天】在代码与逻辑交织的世界中,我从一名数据库新手出发,通过不断探索与实践,最终成为熟练掌握JDBC的开发者。这段旅程充满挑战与惊喜,从建立数据库连接到执行SQL语句,再到理解事务管理和批处理等高级功能,每一步都让我对JDBC有了更深的认识。示例代码展示了如何使用`DriverManager.getConnection()`连接数据库,并利用`PreparedStatement`执行参数化查询,有效防止SQL注入。
365 5
|
SQL 安全 数据库
惊!Python Web安全黑洞大曝光:SQL注入、XSS、CSRF,你中招了吗?
在数字化时代,Web应用的安全性至关重要。许多Python开发者在追求功能时,常忽视SQL注入、XSS和CSRF等安全威胁。本文将深入剖析这些风险并提供最佳实践:使用参数化查询预防SQL注入;通过HTML转义阻止XSS攻击;在表单中加入CSRF令牌增强安全性。遵循这些方法,可有效提升Web应用的安全防护水平,保护用户数据与隐私。安全需持续关注与改进,每个细节都至关重要。
272 5
|
SQL 安全 数据库
深度揭秘:Python Web安全攻防战,SQL注入、XSS、CSRF一网打尽!
在Web开发领域,Python虽强大灵活,却也面临着SQL注入、XSS与CSRF等安全威胁。本文将剖析这些常见攻击手段,并提供示例代码,展示如何利用参数化查询、HTML转义及CSRF令牌等技术构建坚固防线,确保Python Web应用的安全性。安全之路永无止境,唯有不断改进方能应对挑战。
263 5
|
SQL 安全 数据库
深度揭秘:Python Web安全攻防战,SQL注入、XSS、CSRF一网打尽!
在Web开发领域,Python虽强大灵活,但安全挑战不容小觑。本文剖析Python Web应用中的三大安全威胁:SQL注入、XSS及CSRF,并提供防御策略。通过示例代码展示如何利用参数化查询、HTML转义与CSRF令牌构建安全防线,助您打造更安全的应用。安全是一场持久战,需不断改进优化。
167 3
|
SQL 安全 数据安全/隐私保护
Python Web安全大挑战:面对SQL注入、XSS、CSRF,你准备好了吗?
在构建Python Web应用时,安全性至关重要。本文通过三个真实案例,探讨了如何防范SQL注入、XSS和CSRF攻击。首先,通过参数化查询替代字符串拼接,防止SQL注入;其次,利用HTML转义机制,避免XSS攻击;最后,采用CSRF令牌验证,保护用户免受CSRF攻击。这些策略能显著增强应用的安全性,帮助开发者应对复杂的网络威胁。安全是一个持续的过程,需不断学习新知识以抵御不断变化的威胁。
245 1
|
SQL 安全 数据库
Python Web开发者必看!SQL注入、XSS、CSRF全面解析,守护你的网站安全!
在Python Web开发中,构建安全应用至关重要。本文通过问答形式,详细解析了三种常见Web安全威胁——SQL注入、XSS和CSRF,并提供了实用的防御策略及示例代码。针对SQL注入,建议使用参数化查询;对于XSS,需对输出进行HTML编码;而防范CSRF,则应利用CSRF令牌。通过这些措施,帮助开发者有效提升应用安全性,确保网站稳定运行。
208 1

热门文章

最新文章