【原创】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停止使用,看下代码
//获取请求的Url地址
var ipAddress = DotNet.Business.Utilities.GetIPAddress(true);
//必须是内网Ip请求才可以调用接口,做安全检查,不符合要求,直接返回
if (!IpHelper.IsLocalIp(ipAddress))
{
result = (int)MessageStatus.IpError;
return result;
}
代码其实没有特别多,就几行代码,这样就可以达到安全的要求了,客户端调用必须填写内网的域名或者IP请求地址,这样程序才能通过检查,我们来看下获取IP地址的这个方法,参数true就是代表了你的服务器是否启用了代理方式,一般服务器如果没有通过nginx代理的话就可以不填写了,如果服务器是被代理过的一定要填写true,这样才可以获取到请求客户端的真是IP地址。
/// <summary>
/// 获取客户端ip地址
/// </summary>
/// <param name="transparent">是否使用了代理</param>
/// <returns>ip地址</returns>
public static string GetIPAddress(bool transparent = false)
{
string ip = string.Empty;
if (System.Web.HttpContext.Current != null)
{
if (transparent)
{
if (HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] != null)
{
ip = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"].ToString();
}
}
if (string.IsNullOrWhiteSpace(ip))
{
if (HttpContext.Current.Request.ServerVariables["HTTP_VIA"] != null)
{
ip = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"].ToString();
}
else
{
ip = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"].ToString();
}
}
}
return ip;
}
接下来我们看下检查是否是本地IP地址的方法,内网地址一般都是192.168等等开头的IP是服务器的内网地址,所以我们判断一下开头就可以得到是否是内网IP的结果。
/// <summary>
/// 检查是否是内网IP
/// </summary>
/// <param name="ipAddress"></param>
/// <returns></returns>
public static bool IsLocalIp(string ipAddress)
{
bool result = false;
if (!string.IsNullOrEmpty(ipAddress))
{
if (ipAddress.StartsWith("192.168.")
|| ipAddress.StartsWith("172.")
|| ipAddress.StartsWith("10."))
{
result = true;
}
}
return result;
}
- Sql安全
对于前台请求的普通文本框,入库之前一定要做防止Sql语句检查,在通用权限管理的代码中,我们一般使用强类型的实体进行数据库的增删改查,不适用拼接Sql语句的方式进行数据库操作, 本人一直很反感拼接Sql然后提交数据库执行,虽然这个在调试的时候很好很快的找到Sql语句的错误在哪里,但是从程序严谨的角度思考这是不正确的,面向对象告诉我们多使用实体,多使用强类型。还在拼接Sql语句一般都是刚进入工作的菜鸟喜欢干的事情,所以开发中一定要多使用ORM快速开发框架(我个人推荐通用权限管理ORM开发框架),兼容多个数据库,可以灵活切换,执行速度快,UI层不拼接Sql语句,参数化查询,多表查询,分页。
对于Sql注入漏洞,可以参考一下 Sql注入漏洞,对于我们提交到后台的参数值我们一定要做安全性检查。
#region public static string SqlSafe(string value) 检查参数的安全性
/// <summary>
/// 检查参数的安全性
/// </summary>
/// <param name="value">参数</param>
/// <returns>安全的参数</returns>
public static string SqlSafe(string value)
{
value = value.Replace("'", "''");
// value = value.Replace("%", "'%");
return value;
}
#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框架可以帮助我们在工作中应对一些简单的界面,节约时间,就是节约生命。
正在看本人博客的这位童鞋,我看你气度不凡,谈吐间隐隐有王者之气,日后必有一番作为!旁边有“推荐”二字,你就顺手把它点了吧,相得准,我分文不收;相不准,你也好回来找我!
【原创】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/ ...
随机推荐
- [原创]Android自定义View之IndicatorView,显示当前tab页所处位置的View
概述 Android IndicatorView的灵感来源于SlidingTabView,虽然有句"不重复"造轮子在先,本着练手的目的,还是写了一个功能较为简单的类似view. 其 ...
- SQL SERVER 移动系统数据库
移动系统数据库在下列情况下可能很有用: 故障恢复.例如,数据库处于可疑模式下或因硬件故障而关闭. 计划的重定位. 为预定的磁盘维护操作而进行的重定位. 移动 Master 数据库 在“开始”菜 ...
- 教你在Excel里做GA的水平百分比图的详细步骤(图文教程)-成为excel大师(1)
GA报表除了默认的表格方式显示数据外,还支持饼图,水平百分比图,数据透视图等展现方式,其中水平百分比图在可视化看流量时最为方便,就像这样: 那么当我们要在Excel里做类似的效果应该怎么做呢?尤其是数 ...
- Android QQ空间浏览图片动画特效的实现(※)
1 http://blog.csdn.net/yangblocker/article/details/12680247 2 photoview 3 nineoldandroid
- Oracle 11g EM安全证书问题无法访问的解决办法
OS: Windows Server 2012 Oracle: 11g R2 上一篇 Oracle 11g EM删除重建的方法 通过命令的方式重建了EM,启动也成功 emctl status dbco ...
- android一键分享功能不使用任何第三方sdk
在android中有自带的一键分享功能,不过它会把所有带分享的应用都找出来,如果我们只需要一些常见的分享应用,该如何做呢? 下面看我的效果图(横屏和竖屏自动适配): 接下来看我的调用(支持图片和文字分 ...
- git merge之squash
看CM源码时,发现历史记录里有很多squash,于是google了解了一下. Git相对于CVS和SVN的一大好处就是merge非常方便,只要指出branch的名字就好了,如: 1 2 3 4 5 $ ...
- 【原】Configuring Oracle Data Guard In Physical Standby Database
作者:david_zhang@sh [转载时请以超链接形式标明文章] http://www.cnblogs.com/david-zhang-index/p/5042640.html参照文档:https ...
- 我是如何用Go语言搭建自己的博客的
前言: 话说,已经很久没有在博客园更新博客了,之前写的关于go语言的系列学习文章<让我们一起Go>也由于种种原因一度中断.但是,正如我之前在文章中所写,可以慢慢来,但是对于Go语言的学习却 ...
- How to change statusbar text color to dark on android 4.4
Because I haven't enough votes, so post picture at here, thank you. Almost 2 weeks ago, I was search ...