在通常的權限系統裏面,可能常常會看到系統的黑名單或者白名單的攔截功能。在通常權限系統裏面,常見的黑名單就是禁止用戶在某些IP上登陸系統,白名單就是容許用戶只在某些IP上登陸系統。本隨筆主要介紹在個人權限系統裏面,如何實現這個黑白名單的功能,以及介紹在其中應用到的IP對比操做,IP段判斷等操做代碼。ide
要完成黑名單的攔截和白名單的放行,咱們須要進行名單的配置操做,咱們把相關的配置放到列表裏面進行展現,能夠添加多個黑名單或者白名單,以下界面所示。函數
能夠單擊新建按鈕進行添加一條記錄,或者在已有記錄上雙擊黑白名單能夠進行編輯,界面以下所示。性能
在上面的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是否在這個區間裏面。日誌
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