ASP.NET MVC 5使用Filter過濾Action參數防止sql注入

在開發程序的過程當中,稍微不注意就會隱含有sql注入的危險。今天我就來講下,ASP.NET mvc 5使用Filter過濾Action參數防止sql注入,讓你代碼安全簡潔。不用每下地方對參數的值都進行檢查,看是用戶輸入的內容是否有危險的sql。若是每一個地方都要加有幾個缺點:sql

一、工做量大數據庫

二、容易遺漏安全

三、不容易維護mvc

下面我經過寫一個過濾防止sql的特性類,對Action執行前對Action的參數進行處理,若是有其值有sql語句,就會這些非法字符替換爲空字符串。spa

1、sql注入的例子:

上面的輸入有兩個輸入框,用戶能夠輸入任何的值,包括有sql注入的值。code

後臺代碼:orm

AdminController.csblog

複製代碼
public class AdminController : Controller
    {
        public ActionResult Index(string name = "", string loginName = "", int page = 1)
        {
            ViewBag.Name = name;
            ViewBag.LoginName = loginName;
            var r = DAdmin.GetList(name, loginName, page, 2);
            return View(r);
        }
    }
}
複製代碼

DAdmin.cs:繼承

複製代碼
public class DAdmin
{
    public static PageDataView<MSys_Admin> GetList(string name, string loginName, int page,int pageSize=10)
    {
        PageCriteria criteria = new PageCriteria();
        criteria.Condition = "1=1";
        if (!string.IsNullOrEmpty(name))
            criteria.Condition += string.Format(" and Name like '%{0}%'", name);
        if (!string.IsNullOrEmpty(loginName))
            criteria.Condition += string.Format(" and LoginName like '%{0}%'", loginName);
        criteria.CurrentPage = page;
        criteria.Fields = "*";
        criteria.PageSize = pageSize;
        criteria.TableName = "Sys_Admin a";
        criteria.PrimaryKey = "UID";
        var r = Common.GetPageData<MSys_Admin>(criteria);
        return r;
    }
}
複製代碼

上面對用戶輸入的name和loginName兩個參數沒有判斷是否有sql注入的非法字符,就直接拼接到sql語句,到數據庫中執行,這樣是很是危險的。接口

一、好比用戶在name輸入這樣的內容:

%'--%

這樣拼接出來的sql語句就成了

SELECT * FROM Sys_Admin WHERE Name like '%'--%'

這樣「--」是sql的註釋標記後面再拼接的sql語句都當成註釋了,這樣有效的就成了這樣的sql語句:

SELECT * FROM Sys_Admin WHERE Name like '%'

這表示顯示所有的記錄。若是是登陸的sql就會跳過用戶名、密碼的驗證。 

二、若是用戶name輸入內容帶有insert或delete或者drop,好比:

namer人值爲:%';DELETE FROM Sys_Admin--%

拼接成的sql成了:

SELECT * FROM Sys_Admin WHERE Name like '%';DELETE FROM Sys_Admin--%'

這樣一執行就把Sys_Admin表的記錄所有刪除了。

總結:上面能夠看到這種sql注入是多麼的危險。

2、解決MVC sql注入方案

一、定義一個防止sql注入的字符串輔助類

複製代碼
{
    public static string FilterSql(string s)
    {
        if (string.IsNullOrEmpty(s)) return string.Empty;
        s = s.Trim().ToLower();
        s = ClearScript(s);
        s = s.Replace("=", "");
        s = s.Replace("'", "");
        s = s.Replace(";", "");
        s = s.Replace(" or ", "");
        s = s.Replace("select", "");
        s = s.Replace("update", "");
        s = s.Replace("insert", "");
        s = s.Replace("delete", "");
        s = s.Replace("declare", "");
        s = s.Replace("exec", "");
        s = s.Replace("drop", "");
        s = s.Replace("create", "");
        s = s.Replace("%", "");
        s = s.Replace("--", "");
        return s;
    }
}
複製代碼

這個類對上面sql相關的字符串都替換掉。

二、定義一個用來檢查並處理Action參數的特性類

複製代碼
public class AntiSqlInjectAttribute:FilterAttribute,IActionFilter
{
    public void OnActionExecuted(ActionExecutedContext filterContext)
    {
        
    }
 
    public void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var actionParameters = filterContext.ActionDescriptor.GetParameters();
        foreach (var p in actionParameters)
        {
            if (p.ParameterType == typeof(string))
            {
                if (filterContext.ActionParameters[p.ParameterName] != null)
                {
                    filterContext.ActionParameters[p.ParameterName] = StringHelper.FilterSql(filterContext.ActionParameters[p.ParameterName].ToString());
                }
            }
        }
    }
}
複製代碼

說明:這個特性類是繼承了類FilterAttribute和實現了接口IActionFilter,這裏在方法OnActionExecuting處理Action的參數,OnActionExecuting是在Action執行以前運行的方法,而OnActionExecuted是在Action執行以後運行的方法。

p.ParameterType == typeof(string)

由於sql注入只有參數類型爲字符串的時候纔有可能因此這裏只對Action參數爲字符串的參數進行處理。

filterContext.ActionParameters[p.ParameterName] = 
StringHelper.FilterSql(filterContext.ActionParameters[p.ParameterName].ToString());
是用過濾以後的安全的Action參數值替換原來的原始值。

三、防止sql注入特性類的在MVC的Controller中的使用

複製代碼
public class AdminController : Controller
{
    [AntiSqlInject]
    public ActionResult Index(string name = "", string loginName = "", int page = 1)
    {
        ViewBag.Name = name;
        ViewBag.LoginName = loginName;
        var r = DAdmin.GetList(name, loginName, page, 2);
        return View(r);
    }
}
複製代碼

須要對Action的參數進行sql檢查,只用在前面加上,上面定義的特性類AntiSqlInject。這個特性類能夠用在任何的須要防止sql注入的Action上,根本不用對手動的去過濾程序中獲取到的全部參數,安全、方便簡潔

相關文章
相關標籤/搜索