接触通用权限已经一年,如今使用已经很熟练,分享通用权限管理下面的一些好的开发思想。 html
安全漏洞对于一个小项目来讲,可能不是特别的重视,对于一个大项目来讲,这是特别重要须要注意的,特别是在项目开发中的就要警戒,下面我列举一些项目开发中须要注意的安全 nginx
软件开发中,用到最多的两个HTML元素就是input文本框和button标签,当用户经过键盘,鼠标操做文本框将文字内容输入,点击提交咱们须要第一步就进行数据校验。程序员
须要的正则表达式用到每一个文本框中,这里共享一个收集的比较好的正则表达式连接经常使用正则表达式 正则表达式
经过一些页面安全检查工具进行检测,这里先列举咱们开发中用到的安全检查工具AppScan Source,它的一些使用技巧,这里也给出一个连接,AppScan使用分享 数据库
开发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语句通常都是刚进入工做的菜鸟喜欢干的事情,因此开发中必定要多使用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
看下完整的分页请求案例代码,这就是通用权限管理的一些安全小总结
#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
好的ORM框架能够帮助咱们在工做中应对一些简单的界面,节约时间,就是节约生命。
正在看本人博客的这位童鞋,我看你气度不凡,谈吐间隐隐有王者之气,往后必有一番做为!旁边有“推荐”二字,你就顺手把它点了吧,相得准,我分文不收;相不许,你也好回来找我!