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/ ...
 
随机推荐
- 序列变换(Lis变形)
			
序列变换 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submi ...
 - VF(动态规划)
			
VF 时间限制:1000 ms | 内存限制:65535 KB 难度:2 描述 Vasya is the beginning mathematician. He decided to make a ...
 - mysql的常用操作的封装
			
1.概述: 为了把繁琐的操作简化成简单的类,设计了2个类用来封装了mysql的常用操作,以便使用者可以方便地使用. 2.组成 1)数据库操作类CDatabaseConnect 2)SQL对象类CSql ...
 - Cocos2d-x游戏开发CCBAnimationManager控制动画
			
CocosBuilder能方便的编辑各种动画.大部分动画都是以独立片段的形式存在的. 须要由程序来控制何时播放. 管理ccbi文件的动画播放有个专门的类:CCBAnimationManager 大致的 ...
 - Android系统Surface机制的SurfaceFlinger服务的线程模型分析
			
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8062945 在前面两篇文章中,我们分析了Sur ...
 - MFC多线程内存泄漏问题&解决方法
			
在用visual studio进行界面编程时(如MFC),前台UI我们能够通过MFC的消息循环机制实现.而对于后台的数据处理.我们可能会用到多线程来处理. 那么对于大多数人(尤其是我这样的菜鸟),一个 ...
 - css直接写出小三角
			
在开发移动端项目时,总是遇到很多小三角,之前一直用图片,感觉好麻烦,今天尝试了直接用CSS写出小三角!先看看如何写出各种小三角! /*箭头向上*/ .arrow-up { ; ; border-lef ...
 - [AngularJS系列(4)] 那伤不起的provider们啊~ (Provider, Value, Constant, Service, Factory, Decorator)(转)
			
用AngularJS做项目,但凡用过什么service啊,factory啊,provider啊,开始的时候晕没晕?!晕没晕?!感觉干的事儿都差不多啊,到底用哪个啊?!别告诉我你们几个就是为了跟我炫耀兄 ...
 - [Effective C++系列]-为多态基类声明Virtual析构函数
			
Declare destructors virtual in polymorphic base classes. [原理] C++指出,当derived class对象经由一个由base clas ...
 - C语言-getopt函数
			
#include<unistd.h> int getopt(int argc,char *const argv[],const char *optstring); extern char ...