1. 程式人生 > >AOP實踐--ASP.NET MVC 5使用Filter過濾Action引數防止sql注入,讓你程式碼安全簡潔

AOP實踐--ASP.NET MVC 5使用Filter過濾Action引數防止sql注入,讓你程式碼安全簡潔

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

1、工作量大

2、容易遺漏

3、不容易維護

下面我通過寫一個過濾防止sql的特性類,對Action執行前對Action的引數進行處理,如果有其值有sql語句,就會這些非法字元替換為空字串。

一、sql注入的例子:

上面的輸入有兩個輸入框,使用者可以輸入任何的值,包括有sql注入的值。

後臺程式碼:

AdminController.cs

  1. public
    classAdminController:Controller
  2. {
  3. publicActionResultIndex(string name ="",string loginName ="",int page =1)
  4. {
  5. ViewBag.Name= name;
  6. ViewBag.LoginName= loginName;
  7. var r =DAdmin.GetList(name, loginName, page,2);
  8. returnView(r);
  9. }
  10. }
  11. }
DAdmin.cs:
  1. publicclassDAdmin
  2. {
  3. publicstaticPageDataView<MSys_Admin>GetList(string
    name,string loginName,int page,int pageSize=10)
  4. {
  5. PageCriteria criteria =newPageCriteria();
  6. criteria.Condition="1=1";
  7. if(!string.IsNullOrEmpty(name))
  8. criteria.Condition+=string.Format(" and Name like '%{0}%'", name);
  9. if(!string.IsNullOrEmpty(loginName))
  10. criteria.Condition+=string.Format(" and LoginName like '%{0}%'"
    , loginName);
  11. criteria.CurrentPage= page;
  12. criteria.Fields="*";
  13. criteria.PageSize= pageSize;
  14. criteria.TableName="Sys_Admin a";
  15. criteria.PrimaryKey="UID";
  16. var r =Common.GetPageData<MSys_Admin>(criteria);
  17. return r;
  18. }
  19. }

上面對使用者輸入的name和loginName兩個引數沒有判斷是否有sql注入的非法字元,就直接拼接到sql語句,到資料庫中執行,這樣是非常危險的。

1、比如使用者在name輸入這樣的內容:

%'--%

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

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

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

SELECT * FROM Sys_Admin WHERE Name like '%'

這表示顯示全部的記錄。如果是登入的sql就會跳過使用者名稱、密碼的驗證。

2、如果使用者name輸入內容帶有insert或delete或者drop,比如:

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

拼接成的sql成了:

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

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

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

二、解決MVC sql注入方案

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

  1. publicclassStringHelper
  2. {
  3. publicstaticstringFilterSql(string s)
  4. {
  5. if(string.IsNullOrEmpty(s))returnstring.Empty;
  6. s = s.Trim().ToLower();
  7. s =ClearScript(s);
  8. s = s.Replace("=","");
  9. s = s.Replace("'","");
  10. s = s.Replace(";","");
  11. s = s.Replace(" or ","");
  12. s = s.Replace("select","");
  13. s = s.Replace("update","");
  14. s = s.Replace("insert","");
  15. s = s.Replace("delete","");
  16. s = s.Replace("declare","");
  17. s = s.Replace("exec","");
  18. s = s.Replace("drop","");
  19. s = s.Replace("create","");
  20. s = s.Replace("%","");
  21. s = s.Replace("--","");
  22. return s;
  23. }
  24. }
這個類對上面sql相關的字串都替換掉。

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

  1. publicclassAntiSqlInjectAttribute:FilterAttribute,IActionFilter
  2. {
  3. publicvoidOnActionExecuted(ActionExecutedContext filterContext)
  4. {
  5. }
  6. publicvoidOnActionExecuting(ActionExecutingContext filterContext)
  7. {
  8. var actionParameters = filterContext.ActionDescriptor.GetParameters();
  9. foreach(var p in actionParameters)
  10. {
  11. if(p.ParameterType==typeof(string))
  12. {
  13. if(filterContext.ActionParameters[p.ParameterName]!=null)
  14. {
  15. filterContext.ActionParameters[p.ParameterName]=StringHelper.FilterSql(filterContext.ActionParameters[p.ParameterName].ToString());
  16. }
  17. }
  18. }
  19. }
  20. }

說明:這個特性類是繼承了類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引數值替換原來的原始值。

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

  1. publicclassAdminController:Controller
  2. {
  3. [AntiSqlInject]
  4. publicActionResultIndex(string name ="",string loginName ="",int page =1)
  5. {
  6. ViewBag.Name= name;
  7. ViewBag.LoginName= loginName;
  8. var r =DAdmin.GetList(name, loginName, page,2);
  9. returnView(r);
  10. }
  11. }
需要對Action的引數進行sql檢查,只用在前面加上,上面定義的特性類AntiSqlInject。這個特性類可以用在任何的需要防止sql注入的Action上,根本不用對手動的去過濾程式中獲取到的所有引數,安全、方便簡潔。