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
1 2 3 4 5 6 7 8 9 10 | 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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注入的字符串辅助类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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参数的特性类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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中的使用
1 2 3 4 5 6 7 8 9 10 11 | 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上,根本不用对手动的去过滤程序中获取到的所有参数,安全、方便简洁。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现