C#通用权限管理-程序安全检查,这些你一定要考虑到位
接触通用权限已经一年,现在使用已经很熟练,分享通用权限管理下面的一些好的开发思想。
安全漏洞对于一个小项目来说,可能不是特别的重视,对于一个大项目来说,这是特别重要需要注意的,特别是在项目开发中的就要警惕,下面我列举一些项目开发中需要注意的安全
- 页面文本框的检查,每个文本框填写的内容是什么类型就是必须用正则表达式进行强制限制,不能随便输入无用的信息,这是第一步
- 对于C/S的程序,我们可以直接用正则表达式来限制,对于B/S的页面程序,我们也是需要js验证和后台代码的验证,因为浏览器可以禁止js,让js不起作用,所以我们采取的方式就是两步走,js验证后,需要后台对数据还要严格的校验,防止恶意数据进入数据库,守好大门很重要。
- 接口调用安全,通过Post和Get调用接口,知道了服务器的外网IP可以直接调用,所以尽量使用内网,这个就是很大的安全隐患。
- 防止Sql注入,特别非数字的文本框,用户直接可以填写update语句,必须要检查,也可以通过限制文本框的字符长度来控制,有很多程序员总是忘记这一点,字符串长度要和数据库表中的字段通过计算的出来,不能太长也不能太短。
软件开发中,用到最多的两个HTML元素就是input文本框和button标签,当用户通过键盘,鼠标操作文本框将文字内容输入,点击提交我们需要第一步就进行数据校验。
B/S文本框
需要的正则表达式用到每个文本框中,这里共享一个收集的比较好的正则表达式链接常用正则表达式
通过一些页面安全检查工具进行检测,这里先列举我们开发中用到的安全检查工具AppScan Source,它的一些使用技巧,这里也给出一个链接,AppScan使用分享
- C/S文本框
开发DevExpress Winform程序的Dev提供了很好的正则限制,如图1
- 接口安全
当我们的接口通过外网调用的时候是很不安全的,别人知道了URL后可以很轻松的进行调用,由于公司短信接口现在是我负责,每天都在不停的调用发送短信的接口,很多客户端进行调动,产生的短信都有上万条,如果被黑客知道了,那这个就是短信的轰炸机了,所以为了安全起见在接口中做了一下处理,通过内网IP调用接口,外网IP停止使用,看下代码
1 //获取请求的Url地址
2 var ipAddress = DotNet.Business.Utilities.GetIPAddress(true);
3 //必须是内网Ip请求才可以调用接口,做安全检查,不符合要求,直接返回
4 if (!IpHelper.IsLocalIp(ipAddress))
5 {
6 result = (int)MessageStatus.IpError;
7 return result;
8 }
代码其实没有特别多,就几行代码,这样就可以达到安全的要求了,客户端调用必须填写内网的域名或者IP请求地址,这样程序才能通过检查,我们来看下获取IP地址的这个方法,参数true就是代表了你的服务器是否启用了代理方式,一般服务器如果没有通过nginx代理的话就可以不填写了,如果服务器是被代理过的一定要填写true,这样才可以获取到请求客户端的真是IP地址。
1 /// <summary>
2 /// 获取客户端ip地址
3 /// </summary>
4 /// <param name="transparent">是否使用了代理</param>
5 /// <returns>ip地址</returns>
6 public static string GetIPAddress(bool transparent = false)
7 {
8 string ip = string.Empty;
9 if (System.Web.HttpContext.Current != null)
10 {
11 if (transparent)
12 {
13 if (HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] != null)
14 {
15 ip = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"].ToString();
16 }
17 }
18 if (string.IsNullOrWhiteSpace(ip))
19 {
20 if (HttpContext.Current.Request.ServerVariables["HTTP_VIA"] != null)
21 {
22 ip = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"].ToString();
23 }
24 else
25 {
26 ip = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"].ToString();
27 }
28 }
29 }
30 return ip;
31 }
接下来我们看下检查是否是本地IP地址的方法,内网地址一般都是192.168等等开头的IP是服务器的内网地址,所以我们判断一下开头就可以得到是否是内网IP的结果。
1 /// <summary>
2 /// 检查是否是内网IP
3 /// </summary>
4 /// <param name="ipAddress"></param>
5 /// <returns></returns>
6 public static bool IsLocalIp(string ipAddress)
7 {
8 bool result = false;
9 if (!string.IsNullOrEmpty(ipAddress))
10 {
11 if (ipAddress.StartsWith("192.168.")
12 || ipAddress.StartsWith("172.")
13 || ipAddress.StartsWith("10."))
14 {
15 result = true;
16 }
17 }
18 return result;
19 }
- Sql安全
对于前台请求的普通文本框,入库之前一定要做防止Sql语句检查,在通用权限管理的代码中,我们一般使用强类型的实体进行数据库的增删改查,不适用拼接Sql语句的方式进行数据库操作, 本人一直很反感拼接Sql然后提交数据库执行,虽然这个在调试的时候很好很快的找到Sql语句的错误在哪里,但是从程序严谨的角度思考这是不正确的,面向对象告诉我们多使用实体,多使用强类型。还在拼接Sql语句一般都是刚进入工作的菜鸟喜欢干的事情,所以开发中一定要多使用ORM快速开发框架(我个人推荐通用权限管理ORM开发框架),兼容多个数据库,可以灵活切换,执行速度快,UI层不拼接Sql语句,参数化查询,多表查询,分页。
对于Sql注入漏洞,可以参考一下 Sql注入漏洞,对于我们提交到后台的参数值我们一定要做安全性检查。
1 #region public static string SqlSafe(string value) 检查参数的安全性
2 /// <summary>
3 /// 检查参数的安全性
4 /// </summary>
5 /// <param name="value">参数</param>
6 /// <returns>安全的参数</returns>
7 public static string SqlSafe(string value)
8 {
9 value = value.Replace("'", "''");
10 // value = value.Replace("%", "'%");
11 return value;
12 }
13 #endregion
看下完整的分页请求案例代码,这就是通用权限管理的一些安全小总结
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
#region public ActionResult List(Pager pager, string beginDate, string endDate, string oldRecordKey, string newValue) 获取修改记录 /// <summary> /// 获取修改记录 /// </summary> /// <param name="pager">分页实体</param> /// <param name="beginDate">开始日期</param> /// <param name="endDate">结束日期</param> /// <param name="oldRecordKey">原主键值,一般是单号</param> /// <param name="newValue">修改后新的值</param> /// <returns></returns> public ActionResult List(Pager pager, string beginDate, string endDate, string oldRecordKey, string newValue) { var dt1 = DateTime.Now; var dbHelper = DbHelperFactory.GetHelper(BaseSystemInfo.BusinessDbType, BaseSystemInfo.BusinessDbConnectionString); var paramaterList = new List<KeyValuePair< string , object >>(); var listWhere = new List< string >(); //查询条件 string conditions = null ; //变更日期范围 if (! string .IsNullOrEmpty(beginDate) && ! string .IsNullOrEmpty(endDate)) { listWhere.Add( string .Format( "{0} BETWEEN TO_DATE({1}, 'yyyy-mm-dd hh24:mi:ss') AND TO_DATE({2}, 'yyyy-mm-dd hh24:mi:ss')" , ZTO_MODIFYEntity.FieldCREATE_DATE, dbHelper.GetParameter( "beginTime" ), dbHelper.GetParameter( "endTime" ))); paramaterList.Add( new KeyValuePair< string , object >( "beginTime" , DbLogic.SqlSafe(Convert.ToDateTime(beginDate + " 00:00:00" ).ToString(BaseSystemInfo.DateTimeFormat)))); paramaterList.Add( new KeyValuePair< string , object >( "endTime" , DbLogic.SqlSafe(Convert.ToDateTime(endDate + " 23:59:59" ).ToString(BaseSystemInfo.DateTimeFormat)))); } //原主键值 if (! string .IsNullOrEmpty(oldRecordKey)) { listWhere.Add( string .Format( " {0} = {1}" , ZTO_MODIFYEntity.FieldRECORED_KEY_OLD, dbHelper.GetParameter(ZTO_MODIFYEntity.FieldRECORED_KEY_OLD))); paramaterList.Add( new KeyValuePair< string , object >(dbHelper.GetParameter(ZTO_MODIFYEntity.FieldRECORED_KEY_OLD), DbLogic.SqlSafe(oldRecordKey))); } //修改后新值 if (! string .IsNullOrEmpty(newValue)) { listWhere.Add( string .Format( " {0} = {1}" , ZTO_MODIFYEntity.FieldVALUE_NEW, dbHelper.GetParameter(ZTO_MODIFYEntity.FieldVALUE_NEW))); paramaterList.Add( new KeyValuePair< string , object >(dbHelper.GetParameter(ZTO_MODIFYEntity.FieldVALUE_NEW), DbLogic.SqlSafe(newValue))); } //不是超级管理员或者高权限用户只能看自己的 if (!HasRole()) { listWhere.Add( string .Format( " {0} = {1}" , ZTO_MODIFYEntity.FieldCREATE_MAN_ID, dbHelper.GetParameter(ZTO_MODIFYEntity.FieldCREATE_MAN_ID))); paramaterList.Add( new KeyValuePair< string , object >(dbHelper.GetParameter(ZTO_MODIFYEntity.FieldCREATE_MAN_ID), UserInfo.Id)); } //获取排序字段 var sortField = Request[ "sort" ]; if ( string .IsNullOrEmpty(sortField)) { sortField = ZTO_MODIFYEntity.FieldCREATE_DATE; } sortField += ( " " + Request[ "direction" ]); int totalRows; if (listWhere.Count > 0) { conditions += string .Join( " AND " , listWhere); //构建查询条件 } //返回列名称 var backFieldList = new [] { string .Format( "({0}||'-'||{1}){0}" ,ZTO_MODIFYEntity.FieldTABLE_CODE,ZTO_MODIFYEntity.FieldTABLE_NAME), ZTO_MODIFYEntity.FieldCREATE_DATE, ZTO_MODIFYEntity.FieldRECORED_KEY_OLD, ZTO_MODIFYEntity.FieldCOLOUM_CODE, ZTO_MODIFYEntity.FieldCOLOUM_NAME, ZTO_MODIFYEntity.FieldVALUE_OLD, ZTO_MODIFYEntity.FieldVALUE_NEW, ZTO_MODIFYEntity.FieldCREATE_MAN }; var dt = DbLogic.GetDataTableByPage(dbHelper, out totalRows, ZTO_MODIFYEntity.TableName, string .Join( "," , backFieldList), pager.pageNo, pager.pageSize, conditions, paramaterList, sortField); Hashtable ht = BuildHt(dt, totalRows, dt1); return Json(ht, JsonRequestBehavior.AllowGet); } #endregion |
C#通用权限管理-程序安全检查,这些你一定要考虑到位的更多相关文章
- 【原创】C#通用权限管理-程序安全检查,这些你一定要考虑到位
接触通用权限已经一年,现在使用已经很熟练,分享通用权限管理下面的一些好的开发思想. 安全漏洞对于一个小项目来说,可能不是特别的重视,对于一个大项目来说,这是特别重要需要注意的,特别是在项目开发中的就要 ...
- 基于吉日嘎拉的通用权限管理Webform版老界面bug修复
虽然弄了新界面<基于吉日嘎底层架构的通用权限管理Web端UI更新:参考DTcms后台界面>,但老界面的一点菜单显示的问题还是让我这种强迫症揪心,终于今晚可以美美的睡觉了. 老代码用了Ses ...
- 基于吉日嘎底层架构的通用权限管理Web端UI更新:参考DTcms后台界面
经一周的研究学习,看了国内的H+.HUI等,国外的PaperDashboardPro.Make.Metronic BootStrap等,最终选定用一个轻量的,适合中国人的,来自DTcms的后台管理UI ...
- winform快速开发平台 -> 通用权限管理之动态菜单
这几个月一直忙APP的项目,没来得及更新项目,想想该抽出时间整理一下开发思路,跟大家分享,同时也希望得到宝贵的建议. 先说一下我们的权限管理的的设计思路,首先一个企业信息化管理系统一定会用到权限管理, ...
- EASYUI+MVC4通用权限管理平台--前言
经过多年的管理信息系统的开发工作,吸取了工作中遇到的一些问题,经过自己的总结,形成了一套比较完整的管理信息系统的通用权限管理基础开发平台. 在软件的开发过程中我们首先需要解决的是UI问题,其次是浏览器 ...
- EASYUI+MVC4通用权限管理平台
通用权限案例平台在经过几年的实际项目使用,并取得了不错的用户好评.在平台开发完成后,特抽空总结一下平台知识,请各位在以后的时间里,关注博客的更新. 1.EASYUI+MVC4通用权限管理平台--前言 ...
- (转)EASYUI+MVC4通用权限管理平台
原文地址:http://www.cnblogs.com/hn731/archive/2013/07/15/3190947.html 通用权限案例平台在经过几年的实际项目使用,并取得了不错的用户好评.在 ...
- 基于asp.net(C#)MVC+前端bootstrap+ztree+lodash+jquery技术-Angel工作室通用权限管理
一.Angel工作室简单通用权限系统简介 AngelRM(Asp.net MVC Web api)是基于asp.net(C#)MVC+前端bootstrap+ztree+lodash+jquery技术 ...
- java中通用权限管理设计(转)
原文地址:http://www.cnblogs.com/a7345678/archive/2008/09/25/1298838.html 转自博客园暗夜精灵-鬼才阁 实现业务系统中的用户权限管理 B/ ...
随机推荐
- Struts2(一)——总体介绍
这篇博客开始将总结一下有关框架的知识,在开发中合适的利用框架会使我们的开发效率大大提高.当今比较流行的开源框架: 关注数据流程的MVC框架 (Struts1/2, WebWork, Spring MV ...
- More is better(并差集)
More is better Time Limit : 5000/1000ms (Java/Other) Memory Limit : 327680/102400K (Java/Other) To ...
- 关于MAC的pkg和mpkg的分别
程序制作完毕后,在mac下通常的方法是要制作一个pkg的安装包,可是你会发现pkg和mpkg的文件出现的比較多,笔者也是经过了一定的试验和尝试,才了解到,pkg是单个文件的pkg,而mpkg事实上是多 ...
- dom4j解析XML的CURD操作
在开发JavaWeb项目中通常是利用XML配置文件来提高应用程序的访问效率,而在配置XML的同时,更多时候是对XML进行解析. 一.解析XML配置文件有两种机制: DOM和SAX的机制: DOM是将整 ...
- 使用JUnit单元测试入门
一.JUnit是什么? JUnit是一个开发源代码的java测试框架,用于编写和运行可重复的测试.它是用于单元测试框架体系xUnit的一个实例(用于java语言).JUnit最初是由Erich Gam ...
- Gulp及组件安装构建
Gulp 是一款基于任务的设计模式的自动化工具,通过插件的配合解决全套前端解决方案,如静态页面压缩.图片压缩.JS合并.SASS同步编译并压缩CSS.服务器控制客户端同步刷新. Gulp安装 全局安装 ...
- 【枚举+数学】【HDU1271】整数对 难度:五颗星
整数对 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submis ...
- for循环、穷举法和迭代
循环:初始条件,循环条件,状态改变,循环体.for(初始条件;循环条件;状态改变){ 循环体}for(int i=1;i<=10;i++){ }例子:100以内与7有关的数.求100以内所有数的 ...
- application,session,cookie三者之间的区别和联系
application: 程序全局变量对象,对每个用户每个页面都有效 session: 用户全局变量,对于该用户的所有操作过程都有效 session主要是在服务器端用,一般对客户端不 ...
- asp.net + Jquery 实现类似Gridview功能 (一)
不知不觉2015年就过去一半了,由于过年前后公司人员陆续离职(这个...),项目忙不过来,从过年来上班就一直在忙,最近项目终于告一段落,开始步入正轨(不用天天赶项目了).所以最近才有时间写这个东西,可 ...