C#进阶-基于.NET Framework 4.x框架实现ASP.NET WebForms项目IP拦截器
创始人
2024-12-29 05:07:01
0

在这篇文章中,我们将探讨如何在 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 {     ///      /// Test 的摘要说明     ///      [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] 注解。

             

4. 在WebService方法上添加注解

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

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

using System.Web.Services; using TestAsmxProject.Filter.SOAP;  namespace TestAsmxProject.Asmx {     ///      /// Test 的摘要说明     ///      [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();                         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] 注解。

                                                                

4. 在WebService方法上添加注解

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

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

using System.Web.Services; using TestAsmxProject.Filter.HTTP;  namespace TestAsmxProject.Asmx {     ///      /// Test 的摘要说明     ///      [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访问控制有所帮助。

相关内容

热门资讯

一分钟揭秘!wepoke有挂的... 自定义新版wepoke系统规律,只需要输入自己想要的开挂功能,一键便可以生成出wepoke专用辅助器...
程序员教你!微扑克辅助工具下载... 程序员教你!微扑克辅助工具下载!(软件透明挂)原来确实是有挂的(有挂规律)(2022已更新)是一款可...
一分钟揭秘!微扑克插件软件透明... 一分钟揭秘!微扑克插件软件透明挂!微扑克插件辅助透视(2021已更新)(哔哩哔哩);原来是有辅助挂的...
推荐十款!wpk微扑克有辅助!... 推荐十款!wpk微扑克有辅助!(软件透明挂)原来真的是有挂的(有挂技巧)(2021已更新)是一款可以...
第三方教程!wpk辅助实时策略... 第三方教程!wpk辅助实时策略建议!(透视辅助)原来确实是有挂的(有挂分享)(2022已更新);1、...
今日焦点!微扑克模拟器透明挂透... 今日焦点!微扑克模拟器透明挂透视器!微扑克模拟器外挂辅助挂(2023已更新)(哔哩哔哩);原来是有辅...
推荐十款!微扑克有挂一直输!(... 自定义新版系统规律,只需要输入自己想要的开挂功能,一键便可以生成出专用辅助器,不管你是想分享给你好友...
我来教大家!wepoke有玄学... 自定义新版wepoke系统规律,只需要输入自己想要的开挂功能,一键便可以生成出wepoke专用辅助器...
最新研发!wepoke技巧!(... 最新研发!wepoke技巧!(辅助透视)原来是有挂猫腻(有挂助手)(2024已更新)是一款可以让一直...
盘点十款!wepoke辅助!(... 盘点十款!wepoke辅助!(透明挂)原来是真的有挂的(有挂解惑)(2024已更新);AI智能教程细...