在一般的權限系統裡面,可能經常會看到系統的黑名單或者白名單的攔截功能。在一般權限系統裡面 ,常見的黑名單就是禁止用戶在某些IP上登錄系統,白名單就是允許用戶只在某些IP上登錄系統。本隨 筆主要介紹在我的權限系統裡面,如何實現這個黑白名單的功能,以及介紹在其中應用到的IP對比操作 ,IP段判斷等操作代碼。
1、黑白名單的配置
要完成黑名單的攔截和白名單的放行,我們需要進行名單的配置操作,我們把相關的配置放到列表裡 面進行展示,可以添加多個黑名單或者白名單,如下界面所示。

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

2、IP段的錄入和對比
在上面的IP輸入中,我們需要確認IP段的起始地址小於結束地址,否則我們對比的時候,就可能發生 混亂,因此需要在用戶輸入的時候進行確認,也就是IP地址的大小對比關系。
輸入內容的檢查代碼如下所示。
/// <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函數,其實是我的擴展方法,注釋如下所示。

IP地址的對比操作,其實就是把IP文本轉換整形數值及性能對比,Compare擴展方法的定義代碼如下 所示。
/// <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));
}
3、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段裡面,這個邏輯可以通過下面的方法進行判斷實現。
/// 檢測指定的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;
}
查看本欄目
4、系統登錄攔截效果

系統攔截IP登錄後,會記錄一條日志到登錄日志裡面,如下所示。

伍華聰 http://www.iqidi.com