博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C#通用权限管理-程序安全检查,这些你一定要考虑到位
阅读量:6523 次
发布时间:2019-06-24

本文共 7715 字,大约阅读时间需要 25 分钟。

接触通用权限已经一年,现在使用已经很熟练,分享通用权限管理下面的一些好的开发思想。

       安全漏洞对于一个小项目来说,可能不是特别的重视,对于一个大项目来说,这是特别重要需要注意的,特别是在项目开发中的就要警惕,下面我列举一些项目开发中需要注意的安全

  1. 页面文本框的检查,每个文本框填写的内容是什么类型就是必须用正则表达式进行强制限制,不能随便输入无用的信息,这是第一步
  2. 对于C/S的程序,我们可以直接用正则表达式来限制,对于B/S的页面程序,我们也是需要js验证和后台代码的验证,因为浏览器可以禁止js,让js不起作用,所以我们采取的方式就是两步走,js验证后,需要后台对数据还要严格的校验,防止恶意数据进入数据库,守好大门很重要。
  3. 接口调用安全,通过Post和Get调用接口,知道了服务器的外网IP可以直接调用,所以尽量使用内网,这个就是很大的安全隐患。
  4. 防止Sql注入,特别非数字的文本框,用户直接可以填写update语句,必须要检查,也可以通过限制文本框的字符长度来控制,有很多程序员总是忘记这一点,字符串长度要和数据库表中的字段通过计算的出来,不能太长也不能太短。

     软件开发中,用到最多的两个HTML元素就是input文本框和button标签,当用户通过键盘,鼠标操作文本框将文字内容输入,点击提交我们需要第一步就进行数据校验。

  • B/S文本框

    需要的正则表达式用到每个文本框中,这里共享一个收集的比较好的正则表达式链接

    通过一些页面安全检查工具进行检测,这里先列举我们开发中用到的安全检查工具,它的一些使用技巧,这里也给出一个链接,    

  • 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         ///  2         /// 获取客户端ip地址 3         ///  4         /// 是否使用了代理 5         /// 
ip地址
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 else25 {26 ip = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"].ToString();27 }28 }29 }30 return ip;31 }

     接下来我们看下检查是否是本地IP地址的方法,内网地址一般都是192.168等等开头的IP是服务器的内网地址,所以我们判断一下开头就可以得到是否是内网IP的结果。

1         ///  2         /// 检查是否是内网IP 3         ///  4         ///  5         /// 
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注入漏洞,可以参考一下 对于我们提交到后台的参数值我们一定要做安全性检查。

1         #region public static string SqlSafe(string value) 检查参数的安全性 2         ///  3         /// 检查参数的安全性 4         ///  5         /// 参数 6         /// 
安全的参数
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

转载于:https://www.cnblogs.com/zhangruisoldier/p/4269920.html

你可能感兴趣的文章
深入了解 Weex
查看>>
Android第三方开源FloatingActionButton(com.getbase.floatingactionbutton)【1】
查看>>
【75位联合作者Nature重磅】AI药神:机器学习模型有望提前五年预测白血病!
查看>>
精通SpringBoot——第二篇:视图解析器,静态资源和区域配置
查看>>
JavaScript基础(六)面向对象
查看>>
总结几点Quartz的经验
查看>>
从veth看虚拟网络设备的qdisc
查看>>
企业的最佳选择?开放式混合云大行其道
查看>>
物联网、自动化的冲击下未来20年职场六大趋势
查看>>
《Java核心技术 卷Ⅱ 高级特性(原书第10版)》一3.6.2 使用StAX解析器
查看>>
9月26日云栖精选夜读:阿里Java代码规约插件即将全球首发,邀您来发布仪式现场...
查看>>
北京市交管局联合高德地图发布北京中考出行提示
查看>>
如何防止应用程序泄密?
查看>>
一文带你看懂物联网开源操作系统
查看>>
什么是实践中真正在用的数据科学系统?
查看>>
新型智慧城市:构建“互联网+”新生活
查看>>
韩企全球首造72层3D NAND芯片 下半年或量产
查看>>
《R语言编程艺术》——1.4 R语言中一些重要的数据结构
查看>>
如何让你的手机比别人最先升级到 Android L
查看>>
阿里云开源编程马拉松入围项目
查看>>