在開發程序的過程當中,稍微不注意就會隱含有sql注入的危險。今天我就來講下,ASP.NET mvc 5使用Filter過濾Action參數防止sql注入,讓你代碼安全簡潔。不用每下地方對參數的值都進行檢查,看是用戶輸入的內容是否有危險的sql。若是每一個地方都要加有幾個缺點:sql
一、工做量大數據庫
二、容易遺漏安全
三、不容易維護mvc
下面我經過寫一個過濾防止sql的特性類,對Action執行前對Action的參數進行處理,若是有其值有sql語句,就會這些非法字符替換爲空字符串。spa
上面的輸入有兩個輸入框,用戶能夠輸入任何的值,包括有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注入是多麼的危險。
{ 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相關的字符串都替換掉。
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參數值替換原來的原始值。
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上,根本不用對手動的去過濾程序中獲取到的全部參數,安全、方便簡潔