zoukankan      html  css  js  c++  java
  • AOP实践—ASP.NET MVC5 使用Filter过滤Action参数防止sql注入,让你代码安全简洁

    在开发程序的过程中,稍微不注意就会隐含有sql注入的危险。今天我就来说下,ASP.NET mvc 5使用Filter过滤Action参数防止sql注入,让你代码安全简洁。不用每下地方对参数的值都进行检查,看是用户输入的内容是否有危险的sql。如果没个地方都要加有几个缺点:

    1、工作量大

    2、容易遗漏

    3、不容易维护

    下面我通过写一个过滤防止sql的特性类,对Action执行前对Action的参数进行处理,如果有其值有sql语句,就会这些非法字符替换为空字符串。

    一、sql注入的例子:

    上面的输入有两个输入框,用户可以输入任何的值,包括有sql注入的值。

    后台代码:

    AdminController.cs

    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语句,到数据库中执行,这样是非常危险的。

    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注入的字符串辅助类

    public class StringHelper
    {
            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相关的字符串都替换掉。

    2、定义一个用来检查并处理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参数值替换原来的原始值。

    3、防止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上,根本不用对手动的去过滤程序中获取到的所有参数,安全、方便简洁。

  • 相关阅读:
    [NOI2019] 回家路线
    [NOIP2016] 天天爱跑步
    [CF1187D] Subarray Sorting
    [THUPC2018] 弗雷兹的玩具商店
    [AGC006C] Rabbit Exercise
    [AGC005F] Many Easy Problems
    [51Nod2558] 选址
    [BZOJ3771] Triple
    [APIO2019] 奇怪装置
    [CTSC2018] 假面
  • 原文地址:https://www.cnblogs.com/li150dan/p/9712951.html
Copyright © 2011-2022 走看看