Winform開發框架之權限管理系統改進的經驗總結(3)-系統登陸黑白名單的實現

在通常的權限系統裏面,可能常常會看到系統的黑名單或者白名單的攔截功能。在通常權限系統裏面,常見的黑名單就是禁止用戶在某些IP上登陸系統,白名單就是容許用戶只在某些IP上登陸系統。本隨筆主要介紹在個人權限系統裏面,如何實現這個黑白名單的功能,以及介紹在其中應用到的IP對比操做,IP段判斷等操做代碼。ide

一、黑白名單的配置

要完成黑名單的攔截和白名單的放行,咱們須要進行名單的配置操做,咱們把相關的配置放到列表裏面進行展現,能夠添加多個黑名單或者白名單,以下界面所示。函數

能夠單擊新建按鈕進行添加一條記錄,或者在已有記錄上雙擊黑白名單能夠進行編輯,界面以下所示。性能

二、IP段的錄入和對比

在上面的IP輸入中,咱們須要確認IP段的起始地址小於結束地址,不然咱們對比的時候,就可能發生混亂,所以須要在用戶輸入的時候進行確認,也就是IP地址的大小對比關係。ui

輸入內容的檢查代碼以下所示。this

        /// <summary>
        /// 實現控件輸入檢查的函數
        /// </summary>
        /// <returns></returns>
        public override bool CheckInput()
        {
            bool result = true;//默認是能夠經過

            #region MyRegion
            if (this.txtName.Text.Trim().Length == 0)
            {
                MessageDxUtil.ShowTips("請輸入顯示名稱");
                this.txtName.Focus();
                result = false;
            }
            else if (this.txtAuthorizeType.Text.Length == 0)
            {
                MessageDxUtil.ShowTips("請選擇受權類型");
                this.txtAuthorizeType.Focus();
                result = false;
            }
            else if (this.txtIPStart.Text.Length == 0)
            {
                MessageDxUtil.ShowTips("請輸入IP起始地址");
                this.txtIPStart.Focus();
                result = false;
            }
            else if (this.txtIPEnd.Text.Length == 0)
            {
                MessageDxUtil.ShowTips("請輸入IP結束地址");
                this.txtIPEnd.Focus();
                result = false;
            }

            IPAddress ip1 = IPAddress.Parse(this.txtIPStart.Text);
            IPAddress ip2 = IPAddress.Parse(this.txtIPEnd.Text);

            if (ip1.Compare(ip2) == 1)
            {
                MessageDxUtil.ShowTips("請IP開始地址不能大於結束地址, 請修改");
                this.txtIPEnd.Focus();
                result = false;
            }

            #endregion

            return result;
        }

上面代碼的IP地址的Compare函數,實際上是個人擴展方法,註釋以下所示。spa

IP地址的對比操做,其實就是把IP文本轉換整形數值及性能對比,Compare擴展方法的定義代碼以下所示。3d

        /// <summary>
        /// IP地址轉換爲INT類型
        /// </summary>
        /// <param name="IP">IP地址</param>
        /// <returns></returns>
        public static int ToInteger(this IPAddress IP)
        {
            int result = 0;

            byte[] bytes = IP.GetAddressBytes();
            result = (int)(bytes[0] << 24 | bytes[1] << 16 | bytes[2] << 8 | bytes[3]);

            return result;
        }

        /// <summary>
        /// 比較兩個IP的大小。若是相等返回0,若是IP1大於IP2返回1,若是IP1小於IP2返回-1。
        /// </summary>
        /// <param name="IP1">IP地址1</param>
        /// <param name="IP2">IP地址2</param>
        /// <returns>若是相等返回0,若是IP1大於IP2返回1,若是IP1小於IP2返回-1。</returns>
        public static int Compare(this IPAddress IP1, IPAddress IP2)
        {
            int ip1 = IP1.ToInteger();
            int ip2 = IP2.ToInteger();
            return (((ip1 - ip2) >> 0x1F) | (int)((uint)(-(ip1 - ip2)) >> 0x1F));
        }

三、IP段的判斷

不管是黑名單仍是白名單,咱們都要實現對IP段的判斷,也就是給定一個IP起始地址和結束地址,構成的IP段,咱們要判斷用戶登錄的IP是否在這個區間裏面。日誌

       bool ipAccess = BLLFactory<BlackIP>.Instance.ValidateIPAccess(ip, userInfo.ID);
       if (ipAccess)
        {
             ........................
            if (userPassword == userInfo.Password)
            {
               ......................

               //記錄用戶登陸日誌
               BLLFactory<LoginLog>.Instance.AddLoginLog(userInfo, systemType, ip, macAddr, "用戶登陸");
            }
        }
       else
       {
           BLLFactory<LoginLog>.Instance.AddLoginLog(userInfo, systemType, ip, macAddr, "用戶登陸操做被黑白名單禁止登錄!");
       }

在ValidateIPAccess函數裏面,除了白名單優先於黑名單的邏輯外,主要的邏輯判斷就是判斷指定的IP是否落在IP段裏面,這個邏輯能夠經過下面的方法進行判斷實現。code

        /// 檢測指定的IP地址是否在兩個IP段中
        /// </summary>
        /// <param name="ip">指定的IP地址</param>
        /// <param name="begip">起始ip</param>
        /// <param name="endip">結束ip</param>
        /// <returns></returns>
        public static bool IsInIp(string ip, string begip, string endip)
        {
            int[] inip, begipint, endipint = new int[4];
            inip = GetIp(ip);
            begipint = GetIp(begip);
            endipint = GetIp(endip);
            for (int i = 0; i < 4; i++)
            {
                if (inip[i] < begipint[i] || inip[i] > endipint[i])
                {
                    return false;
                }
                else if (inip[i] > begipint[i] || inip[i] < endipint[i])
                {
                    return true;
                }
            }
            return true;
        }

四、系統登陸攔截效果

系統攔截IP登陸後,會記錄一條日誌到登陸日誌裏面,以下所示。blog

相關文章
相關標籤/搜索