zoukankan      html  css  js  c++  java
  • Winform开发框架之权限管理系统改进的经验总结(3)-系统登录黑白名单的实现

    在一般的权限系统里面,可能经常会看到系统的黑名单或者白名单的拦截功能。在一般权限系统里面,常见的黑名单就是禁止用户在某些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登录后,会记录一条日志到登录日志里面,如下所示。

  • 相关阅读:
    java中引用数据类型Scanner类和Random类的使用-0509
    java中运算符的理解-0509
    MySQL-ER图
    MySQL-习题
    《大型网站技术架构:核心原理与案例分析》笔记
    rabbitmq php测试使用
    gearman管理工具GearmanManager的安装与使用
    让PHP7达到最高性能的几个Tips
    linux下查看最消耗CPU、内存的进程
    Gearman分布式任务处理系统
  • 原文地址:https://www.cnblogs.com/wuhuacong/p/3493251.html
Copyright © 2011-2022 走看看