/// <summary>
/// A helper method to attempt to discover [known] SqlInjection attacks.
/// </summary>
/// <param name="whereClause">string of the whereClause to check</param>
/// <returns>true if found, false if not found </returns>
public static bool DetectSqlInjection(string whereClause)
{
return RegSystemThreats.IsMatch(whereClause);
}
/// <summary>
/// A helper method to attempt to discover [known] SqlInjection attacks.
/// </summary>
/// <param name="whereClause">string of the whereClause to check</param>
/// <param name="orderBy">string of the orderBy clause to check</param>
/// <returns>true if found, false if not found </returns>
public static bool DetectSqlInjection(string whereClause, string orderBy)
{
return RegSystemThreats.IsMatch(whereClause) || RegSystemThreats.IsMatch(orderBy);
}
现在我们完成了校验用的正则表达式,接下来让我们需要在页面中添加校验功能。
/// <summary>
/// Handles the Load event of the Page control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
// Gets departmentId from http request.
string queryString = Request.QueryString["jobId"];
if (!string.IsNullOrEmpty(queryString))
{
if (!DetectSqlInjection(queryString) && !DetectSqlInjection(queryString, queryString))
{
// Gets data from database.
gdvData.DataSource = GetData(queryString.Trim());
// Binds data to gridview.
gdvData.DataBind();
}
else
{
throw new Exception("Please enter correct field");
}
}
}
}
-- =============================================
-- Author: JKhuang
-- Create date: 12/31/2011
-- Description: Get data from jobs table by specified jobId.
-- =============================================
ALTER PROCEDURE [dbo].[GetJobs]
-- ensure that the id type is int
@jobId INT
AS
BEGIN
-- SET NOCOUNT ON;
SELECT job_id, job_desc, min_lvl, max_lvl
FROM dbo.jobs
WHERE job_id = @jobId
GRANT EXECUTE ON GetJobs TO pubs
END
接着修改我们的Web程序使用参数化的存储过程进行数据查询。
using (var com = new SqlCommand("GetJobs", con))
{
// Uses store procedure.
com.CommandType = CommandType.StoredProcedure;
// Pass jobId to store procedure.
com.Parameters.Add("@jobId", SqlDbType.Int).Value = jobId;
com.Connection.Open();
gdvData.DataSource = com.ExecuteScalar();
gdvData.DataBind();
}
string sql1 = string.Format("SELECT job_id, job_desc, min_lvl, max_lvl FROM jobs WHERE job_id = @jobId");
using (var con = new SqlConnection(ConfigurationManager.ConnectionStrings["SQLCONN1"].ToString()))
using (var com = new SqlCommand(sql1, con))
{
// Pass jobId to sql statement.
com.Parameters.Add("@jobId", SqlDbType.Int).Value = jobId;
com.Connection.Open();
gdvData.DataSource = com.ExecuteReader();
gdvData.DataBind();
}
图8 参数化SQL查询结果
这样我们就可以避免每个数据库操作(尤其一些简单数据库操作)都编写存储过程了,而且当用户具有数据库中jobs表的读权限才可以执行该SQL语句。
前面使用了存储过程和参数化查询,这两种方法都是非常常用的,而针对于.NET Framework的ORM框架也有很多,如:NHibernate,Castle和Entity Framework,这里我们使用比较简单LINQ to SQL。
图 12 添加jobs.dbml文件
var dc = new pubsDataContext();
int result;
// Validates jobId is int or not.
if (int.TryParse(jobId, out result))
{
gdvData.DataSource = dc.jobs.Where(p => p.job_id == result);
gdvData.DataBind();
}
相比存储过程和参数化查询,LINQ to SQL我们只需添加jobs.dbml,然后使用LINQ对表进行查询就OK了。