【原創】C#通用權限管理-程序安全檢查,這些你必定要考慮到位

       接觸通用權限已經一年,如今使用已經很熟練,分享通用權限管理下面的一些好的開發思想。 html

       安全漏洞對於一個小項目來講,可能不是特別的重視,對於一個大項目來講,這是特別重要須要注意的,特別是在項目開發中的就要警戒,下面我列舉一些項目開發中須要注意的安全 nginx

  1. 頁面文本框的檢查,每一個文本框填寫的內容是什麼類型就是必須用正則表達式進行強制限制,不能隨便輸入無用的信息,這是第一步
  2. 對於C/S的程序,咱們能夠直接用正則表達式來限制,對於B/S的頁面程序,咱們也是須要js驗證和後臺代碼的驗證,由於瀏覽器能夠禁止js,讓js不起做用,因此咱們採起的方式就是兩步走,js驗證後,須要後臺對數據還要嚴格的校驗,防止惡意數據進入數據庫,守好大門很重要。
  3. 接口調用安全,經過Post和Get調用接口,知道了服務器的外網IP能夠直接調用,因此儘可能使用內網,這個就是很大的安全隱患。
  4. 防止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

看下完整的分頁請求案例代碼,這就是通用權限管理的一些安全小總結

 

        #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框架能夠幫助咱們在工做中應對一些簡單的界面,節約時間,就是節約生命。

正在看本人博客的這位童鞋,我看你氣度不凡,談吐間隱隱有王者之氣,往後必有一番做爲!旁邊有「推薦」二字,你就順手把它點了吧,相得準,我分文不收;相不許,你也好回來找我!

相關文章
相關標籤/搜索