C#进阶-基于.NET Framework 4.x框架实现ASP.NET WebForms项目IP拦截器

news2024/9/20 1:01:41

在这篇文章中,我们将探讨如何在 ASP.NET WebForms 中实现IP拦截器,以便在 ASMX Web 服务方法HTTP 请求 中根据IP地址进行访问控制。我们将使用自定义的 SoapExtensionIHttpModule 来实现这一功能,并根据常用的两种文本传输协议:SOAP协议HTTP协议进行分别讲解。


一、创建ASMX接口文件

首先,我们创建一个 ASP.NET WebForms 项目,创建 TestAsmxProject.Asmx 文件,并定义里面的 WebService 服务。
如果不会创建 ASMX 文件,可以参考我的上一篇文章:C#进阶-ASP.NET WebForms调用ASMX的WebService接口。

TestAsmxProject.Asmx 代码如下:

using System.Web.Services;

namespace TestAsmxProject.Asmx
{
    /// <summary>
    /// Test 的摘要说明
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消注释以下行。 
    [System.Web.Script.Services.ScriptService]
    public class Test : System.Web.Services.WebService
    {

        [WebMethod]
        public string HelloWorld()
        {
            return "Hello World";
        }

        [WebMethod(Description = "计算两个数的和")]
        public int Add(int a, int b)
        {
            return a + b;
        }

    }
}

从这个类我们可以看到,目前是有两个 WebService 方法:HelloWorld 方法和 Add方法。调用 HelloWorld 方法会返回 "Hello World" 字符串;用 Add 方法,需要传入 ab 两个参数,会返回 ab 相加的和。


二、基于SOAP协议的拦截器实现

创建一个自定义的 SoapExtension 来实现IP拦截。我们还需要一个自定义属性来指定允许的IP地址。

1. 创建IpFilterAttribute类

新建 Filter 文件夹,再在 Filter 文件夹里新建 SOAP 文件夹。

请添加图片描述

SOAP 文件夹里创建 IpFilterAttribute 类。

在这里插入图片描述

在这里插入图片描述

IpFilterAttribute.cs 代码如下:

using System;
using System.Web.Services.Protocols;

namespace TestAsmxProject.Filter.SOAP
{
    [AttributeUsage(AttributeTargets.Method)]
    public class IpFilterAttribute : SoapExtensionAttribute
    {
        public override Type ExtensionType => typeof(IpFilter);

        public override int Priority { get; set; }

        public string[] AllowedIps { get; private set; }

        public IpFilterAttribute(params string[] ips)
        {
            AllowedIps = ips.Length > 0 ? ips : null;
            Priority = 1;
        }
    } 
}

在这里插入图片描述


2. 创建基于SoapExtension的IpFilter注解类

创建 IpFilter.cs,继承 SoapExtension

在这里插入图片描述

IpFilter.cs 代码如下:

using System;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Services.Protocols;

namespace TestAsmxProject.Filter.SOAP
{
    public class IpFilter : SoapExtension
    {
        private string[] allowedIps;

        public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
        {
            var ipFilterAttribute = attribute as IpFilterAttribute;
            return ipFilterAttribute?.AllowedIps;
        }

        public override object GetInitializer(Type serviceType)
        {
            return null;
        }

        public override void Initialize(object initializer)
        {
            allowedIps = initializer as string[];
        }

        public override void ProcessMessage(SoapMessage message)
        {
            switch (message.Stage)
            {
                case SoapMessageStage.BeforeSerialize:
                    break;
                case SoapMessageStage.AfterSerialize:
                    break;
                case SoapMessageStage.BeforeDeserialize:
                    CheckIpValidation(message);
                    break;
                case SoapMessageStage.AfterDeserialize:
                    break;
            }
        }

        private void CheckIpValidation(SoapMessage message)
        {
            try
            {
                string clientIp = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
                if (string.IsNullOrEmpty(clientIp))
                {
                    clientIp = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
                }
                if (!IsValidIp(clientIp))
                {
                    HttpContext.Current.Response.Clear();
                    HttpContext.Current.Response.StatusCode = 403;
                    HttpContext.Current.Response.ContentType = "text/plain";
                    HttpContext.Current.Response.Write("Access denied: Your IP address is not allowed.");
                    HttpContext.Current.Response.End();
                }
            }
            catch (Exception ex)
            {
                throw;
            }
        }

        private bool IsValidIp(string ip)
        {
            string configIps = ConfigurationManager.AppSettings["IpWhiteList"];
            string[] configAllowedIps = !string.IsNullOrWhiteSpace(configIps)
                ? configIps.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                : new string[] { };
            var allAllowedIps = (allowedIps == null ? new string[] { } : allowedIps).Concat(configAllowedIps).ToArray();
            return allAllowedIps.Any(allowIp => ip == allowIp);
        }
    }
}

在这里插入图片描述


3. 配置web.config中IP白名单

web.config 文件中配置白名单IP列表,在 IpFilter.cs 里我们已经写过该逻辑,web.config 文件中白名单内的 IpWhiteList 里的IP是全局白名单,无论 WebService服务方法 上是否有 [IpFilter] 注解。

<configuration>
  <appSettings>
    <add key="IpWhiteList" value="127.0.0.1,192.168.1.1" />
  </appSettings>
</configuration>

4. 在WebService方法上添加注解

WebService服务方法 上使用 [IpFilter] 注解,可以定义该方法的专属IP白名单(包含 web.config 中的全局白名单),如果不设定,则仅使用 web.config 中的白名单。

加了 [IpFilter] 注解后的 TestAsmxProject.Asmx 代码如下:

using System.Web.Services;
using TestAsmxProject.Filter.SOAP;

namespace TestAsmxProject.Asmx
{
    /// <summary>
    /// Test 的摘要说明
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消注释以下行。 
    [System.Web.Script.Services.ScriptService]
    public class Test : System.Web.Services.WebService
    {

        [WebMethod]
        [IpFilter] // 不传入指定IP,使用web.config中的白名单
        public string HelloWorld()
        {
            return "Hello World";
        }

        [WebMethod(Description = "计算两个数的和")]
        [IpFilter("127.0.0.1", "192.168.1.1")] // 此处为该方法的IP白名单,加上web.config中的白名单共同生效
        public int Add(int a, int b)
        {
            return a + b;
        }

    }
}

在这里插入图片描述


三、基于HTTP协议的拦截器实现

接下来,我们创建一个基于HTTP协议的拦截器来实现IP拦截。同样,我们需要一个自定义属性来指定允许的IP地址。

1. 创建IpFilterAttribute类

新建 Filter 文件夹,再在 Filter 文件夹里新建 HTTP 文件夹。

请添加图片描述

SOAP 文件夹里创建 IpFilterAttribute 类。

在这里插入图片描述

在这里插入图片描述

IpFilterAttribute.cs 代码如下:

using System;
using System.Configuration;

namespace TestAsmxProject.Filter.HTTP
{
    [AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
    public sealed class IpFilterAttribute : Attribute
    {
        public string[] AllowedIps { get; private set; }

        public IpFilterAttribute(params string[] ips)
        {
            string configIps = ConfigurationManager.AppSettings["IpWhiteList"];
            var configAllowedIps = !string.IsNullOrEmpty(configIps)
                ? configIps.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                : new string[] { };
            AllowedIps = new string[ips.Length + configAllowedIps.Length];
            ips.CopyTo(AllowedIps, 0);
            configAllowedIps.CopyTo(AllowedIps, ips.Length);
        }

        public bool IsAllowedIp(string userIp)
        {
            return AllowedIps.Any(ip => userIp == ip);
        }
    }
}

2. 创建基于IHttpModule的IpFilter注解类

创建 IpFilter.cs,继承 IHttpModule

在这里插入图片描述

IpFilter.cs 代码如下:

using System;
using System.Linq;
using System.Reflection;
using System.Web;

namespace TestAsmxProject.Filter.HTTP
{
    public class IpFilter : IHttpModule
    {
        public void Init(HttpApplication context)
        {
            context.PreRequestHandlerExecute += new EventHandler(OnPreRequestHandlerExecute);
        }

        private void OnPreRequestHandlerExecute(object sender, EventArgs e)
        {
            HttpApplication application = (HttpApplication)sender;
            HttpContext context = application.Context;
            if (context.Request.Path.Contains(".asmx"))
            {
                string userIp = context.Request.UserHostAddress;
                string methodName = context.Request.PathInfo.Replace("/", "");

                Type webServiceType = GetWebServiceType(context.Request.Path);
                if (webServiceType != null)
                {
                    MethodInfo methodInfo = webServiceType.GetMethod(methodName);
                    if (methodInfo != null)
                    {
                        var attribute = methodInfo.GetCustomAttribute<IpFilterAttribute>();
                        if (attribute != null && !attribute.IsAllowedIp(userIp))
                        {
                            context.Response.StatusCode = 403;
                            context.Response.ContentType = "text/plain";
                            context.Response.Write("Access denied: Your IP address is not allowed.");
                            context.Response.End();
                        }
                    }
                }
            }
        }

        private Type GetWebServiceType(string path)
        {
            string serviceName = path.Split('/')[2].Split('.').First();
            string namespacePrefix = "WebForms.CAS";
            string typeName = $"{namespacePrefix}.{serviceName}";
            Type serviceType = Type.GetType(typeName);
            if (serviceType == null)
            {
                var assemblies = AppDomain.CurrentDomain.GetAssemblies();
                foreach (var assembly in assemblies)
                {
                    serviceType = assembly.GetType(typeName);
                    if (serviceType != null)
                    {
                        break;
                    }
                }
            }
            return serviceType;
        }

        public void Dispose() { }
    }
}

3. 配置web.config中白名单和模块

web.config 文件中配置白名单IP列表,在 IpFilter.cs 里我们已经写过该逻辑,web.config 文件中白名单内的 IpWhiteList 里的IP是全局白名单,无论 WebService服务方法 上是否有 [IpFilter] 注解。

<configuration>
  <appSettings>
    <add key="IpWhiteList" value="127.0.0.1,192.168.1.1" />
  </appSettings>
  <system.web>
    <httpModules>
      <add name="IpFilter" type="TestAsmxProject.Filter.HTTP.IpFilter"/>
    </httpModules>
  </system.web>
  <system.webServer>
    <validation validateIntegratedModeConfiguration="false" />
    <modules runAllManagedModulesForAllRequests="true">
      <add name="IpFilter" type="TestAsmxProject.Filter.HTTP.IpFilter"/>
    </modules>
  </system.webServer>
</configuration>

4. 在WebService方法上添加注解

WebService服务方法 上使用 [IpFilter] 注解,可以定义该方法的专属IP白名单(包含 web.config 中的全局白名单),如果不设定,则仅使用 web.config 中的白名单。

加了 [IpFilter] 注解后的 TestAsmxProject.Asmx 代码如下:

using System.Web.Services;
using TestAsmxProject.Filter.HTTP;

namespace TestAsmxProject.Asmx
{
    /// <summary>
    /// Test 的摘要说明
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消注释以下行。 
    [System.Web.Script.Services.ScriptService]
    public class Test : System.Web.Services.WebService
    {

        [WebMethod]
        [IpFilter] // 不传入指定IP,使用web.config中的白名单
        public string HelloWorld()
        {
            return "Hello World";
        }

        [WebMethod(Description = "计算两个数的和")]
        [IpFilter("127.0.0.1", "192.168.1.1")] // 此处为该方法的IP白名单,加上web.config中的白名单共同生效
        public int Add(int a, int b)
        {
            return a + b;
        }

    }
}

在这里插入图片描述


四、IP拦截器实现总结

通过上述步骤,我们成功实现了在 ASP.NET WebForms 中基于IP地址的访问控制。我们分别使用自定义的 SoapExtensionIHttpModule,实现了对ASMX Web服务方法和HTTP请求的IP拦截。

1. 自定义 SoapExtension

自定义的 SoapExtension 通过重载 ProcessMessage 方法,在SOAP消息处理的不同阶段进行IP地址的验证。通过检查请求的IP地址并与允许的IP列表进行比较,我们可以在消息反序列化之前阻止不符合条件的请求,从而有效地控制对Web服务方法的访问。这种方法特别适用于基于SOAP的Web服务,能够在服务方法调用之前进行精细的访问控制。

2. 自定义 IHttpModule

自定义的 IHttpModule 通过实现 Init 方法并注册 PreRequestHandlerExecute 事件,在每个HTTP请求处理之前执行IP地址验证。通过反射获取请求对应的方法,并检查方法上的自定义属性 IpFilterAttribute,我们可以动态地对特定方法应用IP过滤规则。结合 web.config 中配置的白名单IP地址,这种方法能够灵活地扩展和维护IP访问控制规则,适用于一般的HTTP请求拦截需求。

3. 本文提供方法的实现优势

这种IP拦截器的实现方法不仅增强了应用程序的安全性,还具有良好的扩展性和可维护性。开发者可以根据具体需求,通过配置文件或代码注解灵活地管理允许的IP地址。通过将安全控制逻辑封装在自定义模块和扩展中,可以保持业务代码的简洁和可读性。

希望这篇文章对你在ASP.NET WebForms应用中的IP访问控制有所帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1931181.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

jmeter之变量随机参数化以及解决多线程不会随机变化

参考链接&#xff1a; https://www.cnblogs.com/Testing1105/p/12743475.html jmeter 使用random函数多线程运行时数据不会随机变化&#xff1f;_jmeter 线程组循环执行时 变量不变-CSDN博客 1、如下图所示&#xff0c;需要对请求参数 autor 和phone进行随机参数化 2、目前有…

2024大模型十大趋势

2024大模型十大趋势 关键要点一、机器外脑时代的智慧探索二、机器外脑、创意生成和情感陪伴三、大模型驱动的新未来&#xff1a;AI带来创意转化与机遇四、人物-行为-场景一体化&#xff1a;未来人工智能的新范式五、未来数字内容生产的基础设施六、共创、共建、共享智能美好未来…

Linux - 冯-诺依曼体系结构、初始操作系统

目录 冯•诺依曼体系 结构推导 内存提高效率的方法 数据的流动过程 体系结构相关知识 初始操作系统 定位 设计目的 操作系统之上之下分别有什么 管理精髓&#xff1a;先描述&#xff0c;再组织 冯•诺依曼体系 结构推导 计算机基本工作流程图大致如下&#xff1a; 输入设备&a…

删除windows系统里磁盘的恢复分区

说下我的情况 我买了块固态磁盘&#xff0c;插上主板&#xff0c;发现它自带了系统&#xff0c;这样我开机就会转到这块磁盘&#xff0c;即使在boot里改变也不行&#xff0c;后面我格式化了对应的盘符&#xff0c;但在磁盘管理里&#xff0c;发现有个EFI系统分区和恢复分区存在…

初识并发编程

并发编程的目的是 为 了 让 程序运行得更快&#xff0c;但是&#xff0c;并不是启 动 更多的 线 程就能 让 程序最大限度地并发执 行。在 进 行并 发编 程 时 &#xff0c;如果希望通 过 多 线 程 执 行任 务让 程序运行得更快&#xff0c;会面临 非常多的挑 战 &#xff0c;比…

【Django+Vue3 线上教育平台项目实战】登录功能模块之短信登录与钉钉三方登录

文章目录 前言一、几个关键概念1.HTTP无状态性2.Session机制3.Token认证4.JWT 二、通过手机号验证码登录1.前端短信登录界面2.发送短信接口与短信登录接口3.Vue 设置interceptors拦截器4. 服务端验证采用自定义中间件方式实现5. 操作流程及效果图如下&#xff1a; 三、通过第三…

编程从零基础到进阶(更新中)

题目描述 依旧是输入三个整数&#xff0c;要求按照占8个字符的宽度&#xff0c;并且靠左对齐输出 输入格式 一行三个整数&#xff0c;空格分开 输出格式 输出它们按格式输出的效果&#xff0c;占一行 样例输入 123456789 -1 10 样例输出 123456789-1 10 #include "stdio.…

昇思25天学习打卡营第七天|应用实践/热门LLM及其他AI应用/基于MobileNetv2的垃圾分类

心得 本课程主要介绍垃圾分类代码开发的方法。通过读取本地图像数据作为输入&#xff0c;对图像中的垃圾物体进行检测&#xff0c;并且将检测结果图片保存到文件中。 这个AI是我觉很不错的一个想法。比较解决实际的痛点&#xff0c;就是作为普通人来讲&#xff0c;不可能像专…

「安全知识」叉车超速的危害引发的后果是这样的……

在繁忙的工业环境中&#xff0c;叉车作为不可或缺的物流工具&#xff0c;其安全性直接关系到生产效率和员工生命安全。然而&#xff0c;当叉车驾驶员忽视速度限制&#xff0c;超速行驶时&#xff0c;一系列潜在的危险便悄然滋生。本文将讲解叉车超速的危害以及解决措施&#xf…

pip install安装第三方库 error: Microsoft Visual C++ 14.0 or greater is required

原因&#xff1a; 在windows出现此情况的原因是pip安装的库其中部分代码不是python而是使用C等代码编写&#xff0c;我们安装这种类型的库时需要进行编译后安装。 安装Microsoft C Build Tools软件&#xff0c;但这种方式对于很多人来说过于笨重。&#xff08;不推荐&#xf…

脚本新手必看!一文掌握${}在Shell脚本中的神操作!

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 文章内容 📒📝 变量引用与默认值📝 字符串操作📝 数组与索引📝 参数扩展与模式匹配⚓️ 相关链接 ⚓️📖 介绍 📖 在编程的广阔世界里,隐藏着无数小巧而强大的工具,它们如同魔法般简化着复杂的操作。今天,我将…

黑马头条-环境搭建、SpringCloud

一、项目介绍 1. 项目背景介绍 项目概述 类似于今日头条&#xff0c;是一个新闻资讯类项目。 随着智能手机的普及&#xff0c;人们更加习惯于通过手机来看新闻。由于生活节奏的加快&#xff0c;很多人只能利用碎片时间来获取信息&#xff0c;因此&#xff0c;对于移动资讯客…

深度学习落地实战:基于UNet实现血管瘤超声图像分割

前言 大家好&#xff0c;我是机长 本专栏将持续收集整理市场上深度学习的相关项目&#xff0c;旨在为准备从事深度学习工作或相关科研活动的伙伴&#xff0c;储备、提升更多的实际开发经验&#xff0c;每个项目实例都可作为实际开发项目写入简历&#xff0c;且都附带完整的代…

无人机技术优势及发展详解

一、技术优势 无人机&#xff08;Unmanned Aerial Vehicle&#xff0c;UAV&#xff09;作为一种新兴的空中智能平台&#xff0c;凭借其独特的技术优势&#xff0c;已经在众多领域中展现出强大的应用潜力和实用价值。以下是无人机的主要技术优势&#xff1a; 1. 自主导航与远程…

《昇思25天学习打卡营第19天|Diffusion扩散模型》

什么是Diffusion Model&#xff1f; 什么是Diffusion Model? 如果将Diffusion与其他生成模型&#xff08;如Normalizing Flows、GAN或VAE&#xff09;进行比较&#xff0c;它并没有那么复杂&#xff0c;它们都将噪声从一些简单分布转换为数据样本&#xff0c;Diffusion也是从…

传统墙面装饰已成过去?创意投影互动墙引领新潮流?

你是否曾遐想过&#xff0c;那些日常中屡见不鲜的平凡墙面&#xff0c;能够摇身一变&#xff0c;成为既炫酷又高度互动的奇迹之地&#xff1f;事实上&#xff0c;这并非遥不可及的梦想&#xff0c;只需巧妙融合前沿的投影技术、灵敏的传感器与智能软件系统&#xff0c;便能瞬间…

01 机器学习概述

目录 1. 基本概念 2. 机器学习三要素 3. 参数估计的四个方法 3.1 经验风险最小化 3.2 结构风险最小化 3.3 最大似然估计 3.4 最大后验估计 4. 偏差-方差分解 5. 机器学习算法的类型 6. 数据的特征表示 7. 评价指标 1. 基本概念 机器学习&#xff08;Machine Le…

AdobeInDesign ID软件三网下载+Id教程

简介&#xff1a; InDesign还可以结合其他产品发布适合平板设备的内容。平面设计师和生产艺术家是主要用户&#xff0c;创作和布局期刊出版物、海报和印刷媒体。它还支持导出到EPUB和SWF格式&#xff0c;以创建电子书和数字出版物&#xff0c;包括数字杂志&#xff0c;以及适合…

【linux高级IO(三)】初识epoll

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:Linux从入门到精通⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学更多操作系统知识   &#x1f51d;&#x1f51d; Linux高级IO 1. 前言2. 初识e…

【python】PyQt5的窗口界面的各种交互逻辑实现,轻松掌控图形化界面程序

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…