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

打印 上一主题 下一主题

主题 510|帖子 510|积分 1530

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

一、创建ASMX接口文件

首先,我们创建一个 ASP.NET WebForms 项目,创建 TestAsmxProject.Asmx 文件,并界说内里的 WebService 服务。
如果不会创建 ASMX 文件,可以参考我的上一篇文章:C#进阶-ASP.NET WebForms调用ASMX的WebService接口。
TestAsmxProject.Asmx 代码如下:
  1. using System.Web.Services;
  2. namespace TestAsmxProject.Asmx
  3. {
  4.     /// <summary>
  5.     /// Test 的摘要说明
  6.     /// </summary>
  7.     [WebService(Namespace = "http://tempuri.org/")]
  8.     [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
  9.     [System.ComponentModel.ToolboxItem(false)]
  10.     // 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消注释以下行。
  11.     [System.Web.Script.Services.ScriptService]
  12.     public class Test : System.Web.Services.WebService
  13.     {
  14.         [WebMethod]
  15.         public string HelloWorld()
  16.         {
  17.             return "Hello World";
  18.         }
  19.         [WebMethod(Description = "计算两个数的和")]
  20.         public int Add(int a, int b)
  21.         {
  22.             return a + b;
  23.         }
  24.     }
  25. }
复制代码
从这个类我们可以看到,目前是有两个 WebService 方法:HelloWorld 方法和 Add方法。调用 HelloWorld 方法会返回 "Hello World" 字符串;用 Add 方法,必要传入 a 和 b 两个参数,会返回 a 和 b 相加的和。

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

创建一个自界说的 SoapExtension 来实现IP拦截。我们还必要一个自界说属性来指定允许的IP地址。
1. 创建IpFilterAttribute类

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

在 SOAP 文件夹里创建 IpFilterAttribute 类。


IpFilterAttribute.cs 代码如下:
  1. using System;
  2. using System.Web.Services.Protocols;
  3. namespace TestAsmxProject.Filter.SOAP
  4. {
  5.     [AttributeUsage(AttributeTargets.Method)]
  6.     public class IpFilterAttribute : SoapExtensionAttribute
  7.     {
  8.         public override Type ExtensionType => typeof(IpFilter);
  9.         public override int Priority { get; set; }
  10.         public string[] AllowedIps { get; private set; }
  11.         public IpFilterAttribute(params string[] ips)
  12.         {
  13.             AllowedIps = ips.Length > 0 ? ips : null;
  14.             Priority = 1;
  15.         }
  16.     }
  17. }
复制代码


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

创建 IpFilter.cs,继承 SoapExtension。

IpFilter.cs 代码如下:
  1. using System;
  2. using System.Configuration;
  3. using System.Linq;
  4. using System.Web;
  5. using System.Web.Services.Protocols;
  6. namespace TestAsmxProject.Filter.SOAP
  7. {
  8.     public class IpFilter : SoapExtension
  9.     {
  10.         private string[] allowedIps;
  11.         public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
  12.         {
  13.             var ipFilterAttribute = attribute as IpFilterAttribute;
  14.             return ipFilterAttribute?.AllowedIps;
  15.         }
  16.         public override object GetInitializer(Type serviceType)
  17.         {
  18.             return null;
  19.         }
  20.         public override void Initialize(object initializer)
  21.         {
  22.             allowedIps = initializer as string[];
  23.         }
  24.         public override void ProcessMessage(SoapMessage message)
  25.         {
  26.             switch (message.Stage)
  27.             {
  28.                 case SoapMessageStage.BeforeSerialize:
  29.                     break;
  30.                 case SoapMessageStage.AfterSerialize:
  31.                     break;
  32.                 case SoapMessageStage.BeforeDeserialize:
  33.                     CheckIpValidation(message);
  34.                     break;
  35.                 case SoapMessageStage.AfterDeserialize:
  36.                     break;
  37.             }
  38.         }
  39.         private void CheckIpValidation(SoapMessage message)
  40.         {
  41.             try
  42.             {
  43.                 string clientIp = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
  44.                 if (string.IsNullOrEmpty(clientIp))
  45.                 {
  46.                     clientIp = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
  47.                 }
  48.                 if (!IsValidIp(clientIp))
  49.                 {
  50.                     HttpContext.Current.Response.Clear();
  51.                     HttpContext.Current.Response.StatusCode = 403;
  52.                     HttpContext.Current.Response.ContentType = "text/plain";
  53.                     HttpContext.Current.Response.Write("Access denied: Your IP address is not allowed.");
  54.                     HttpContext.Current.Response.End();
  55.                 }
  56.             }
  57.             catch (Exception ex)
  58.             {
  59.                 throw;
  60.             }
  61.         }
  62.         private bool IsValidIp(string ip)
  63.         {
  64.             string configIps = ConfigurationManager.AppSettings["IpWhiteList"];
  65.             string[] configAllowedIps = !string.IsNullOrWhiteSpace(configIps)
  66.                 ? configIps.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
  67.                 : new string[] { };
  68.             var allAllowedIps = (allowedIps == null ? new string[] { } : allowedIps).Concat(configAllowedIps).ToArray();
  69.             return allAllowedIps.Any(allowIp => ip == allowIp);
  70.         }
  71.     }
  72. }
复制代码


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

在 web.config 文件中设置白名单IP列表,在 IpFilter.cs 里我们已经写过该逻辑,web.config 文件中白名单内的 IpWhiteList 里的IP是全局白名单,无论 WebService服务方法 上是否有 [IpFilter] 注解。
  1. <configuration>
  2.   <appSettings>
  3.     <add key="IpWhiteList" value="127.0.0.1,192.168.1.1" />
  4.   </appSettings>
  5. </configuration>
复制代码

4. 在WebService方法上添加注解

在 WebService服务方法 上使用 [IpFilter] 注解,可以界说该方法的专属IP白名单(包含 web.config 中的全局白名单),如果不设定,则仅使用 web.config 中的白名单。
加了 [IpFilter] 注解后的 TestAsmxProject.Asmx 代码如下:
  1. using System.Web.Services;
  2. using TestAsmxProject.Filter.SOAP;
  3. namespace TestAsmxProject.Asmx
  4. {
  5.     /// <summary>
  6.     /// Test 的摘要说明
  7.     /// </summary>
  8.     [WebService(Namespace = "http://tempuri.org/")]
  9.     [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
  10.     [System.ComponentModel.ToolboxItem(false)]
  11.     // 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消注释以下行。
  12.     [System.Web.Script.Services.ScriptService]
  13.     public class Test : System.Web.Services.WebService
  14.     {
  15.         [WebMethod]
  16.         [IpFilter] // 不传入指定IP,使用web.config中的白名单
  17.         public string HelloWorld()
  18.         {
  19.             return "Hello World";
  20.         }
  21.         [WebMethod(Description = "计算两个数的和")]
  22.         [IpFilter("127.0.0.1", "192.168.1.1")] // 此处为该方法的IP白名单,加上web.config中的白名单共同生效
  23.         public int Add(int a, int b)
  24.         {
  25.             return a + b;
  26.         }
  27.     }
  28. }
复制代码


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

接下来,我们创建一个基于HTTP协议的拦截器来实现IP拦截。同样,我们必要一个自界说属性来指定允许的IP地址。
1. 创建IpFilterAttribute类

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

在 SOAP 文件夹里创建 IpFilterAttribute 类。


IpFilterAttribute.cs 代码如下:
  1. using System;
  2. using System.Configuration;
  3. namespace TestAsmxProject.Filter.HTTP
  4. {
  5.     [AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
  6.     public sealed class IpFilterAttribute : Attribute
  7.     {
  8.         public string[] AllowedIps { get; private set; }
  9.         public IpFilterAttribute(params string[] ips)
  10.         {
  11.             string configIps = ConfigurationManager.AppSettings["IpWhiteList"];
  12.             var configAllowedIps = !string.IsNullOrEmpty(configIps)
  13.                 ? configIps.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
  14.                 : new string[] { };
  15.             AllowedIps = new string[ips.Length + configAllowedIps.Length];
  16.             ips.CopyTo(AllowedIps, 0);
  17.             configAllowedIps.CopyTo(AllowedIps, ips.Length);
  18.         }
  19.         public bool IsAllowedIp(string userIp)
  20.         {
  21.             return AllowedIps.Any(ip => userIp == ip);
  22.         }
  23.     }
  24. }
复制代码

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

创建 IpFilter.cs,继承 IHttpModule。

IpFilter.cs 代码如下:
  1. using System;
  2. using System.Linq;
  3. using System.Reflection;
  4. using System.Web;
  5. namespace TestAsmxProject.Filter.HTTP
  6. {
  7.     public class IpFilter : IHttpModule
  8.     {
  9.         public void Init(HttpApplication context)
  10.         {
  11.             context.PreRequestHandlerExecute += new EventHandler(OnPreRequestHandlerExecute);
  12.         }
  13.         private void OnPreRequestHandlerExecute(object sender, EventArgs e)
  14.         {
  15.             HttpApplication application = (HttpApplication)sender;
  16.             HttpContext context = application.Context;
  17.             if (context.Request.Path.Contains(".asmx"))
  18.             {
  19.                 string userIp = context.Request.UserHostAddress;
  20.                 string methodName = context.Request.PathInfo.Replace("/", "");
  21.                 Type webServiceType = GetWebServiceType(context.Request.Path);
  22.                 if (webServiceType != null)
  23.                 {
  24.                     MethodInfo methodInfo = webServiceType.GetMethod(methodName);
  25.                     if (methodInfo != null)
  26.                     {
  27.                         var attribute = methodInfo.GetCustomAttribute<IpFilterAttribute>();
  28.                         if (attribute != null && !attribute.IsAllowedIp(userIp))
  29.                         {
  30.                             context.Response.StatusCode = 403;
  31.                             context.Response.ContentType = "text/plain";
  32.                             context.Response.Write("Access denied: Your IP address is not allowed.");
  33.                             context.Response.End();
  34.                         }
  35.                     }
  36.                 }
  37.             }
  38.         }
  39.         private Type GetWebServiceType(string path)
  40.         {
  41.             string serviceName = path.Split('/')[2].Split('.').First();
  42.             string namespacePrefix = "WebForms.CAS";
  43.             string typeName = $"{namespacePrefix}.{serviceName}";
  44.             Type serviceType = Type.GetType(typeName);
  45.             if (serviceType == null)
  46.             {
  47.                 var assemblies = AppDomain.CurrentDomain.GetAssemblies();
  48.                 foreach (var assembly in assemblies)
  49.                 {
  50.                     serviceType = assembly.GetType(typeName);
  51.                     if (serviceType != null)
  52.                     {
  53.                         break;
  54.                     }
  55.                 }
  56.             }
  57.             return serviceType;
  58.         }
  59.         public void Dispose() { }
  60.     }
  61. }
复制代码

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

在 web.config 文件中设置白名单IP列表,在 IpFilter.cs 里我们已经写过该逻辑,web.config 文件中白名单内的 IpWhiteList 里的IP是全局白名单,无论 WebService服务方法 上是否有 [IpFilter] 注解。
  1. <configuration>
  2.   <appSettings>
  3.     <add key="IpWhiteList" value="127.0.0.1,192.168.1.1" />
  4.   </appSettings>
  5.   <system.web>
  6.     <httpModules>
  7.       <add name="IpFilter" type="TestAsmxProject.Filter.HTTP.IpFilter"/>
  8.     </httpModules>
  9.   </system.web>
  10.   <system.webServer>
  11.     <validation validateIntegratedModeConfiguration="false" />
  12.     <modules runAllManagedModulesForAllRequests="true">
  13.       <add name="IpFilter" type="TestAsmxProject.Filter.HTTP.IpFilter"/>
  14.     </modules>
  15.   </system.webServer>
  16. </configuration>
复制代码

4. 在WebService方法上添加注解

在 WebService服务方法 上使用 [IpFilter] 注解,可以界说该方法的专属IP白名单(包含 web.config 中的全局白名单),如果不设定,则仅使用 web.config 中的白名单。
加了 [IpFilter] 注解后的 TestAsmxProject.Asmx 代码如下:
  1. using System.Web.Services;
  2. using TestAsmxProject.Filter.HTTP;
  3. namespace TestAsmxProject.Asmx
  4. {
  5.     /// <summary>
  6.     /// Test 的摘要说明
  7.     /// </summary>
  8.     [WebService(Namespace = "http://tempuri.org/")]
  9.     [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
  10.     [System.ComponentModel.ToolboxItem(false)]
  11.     // 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消注释以下行。
  12.     [System.Web.Script.Services.ScriptService]
  13.     public class Test : System.Web.Services.WebService
  14.     {
  15.         [WebMethod]
  16.         [IpFilter] // 不传入指定IP,使用web.config中的白名单
  17.         public string HelloWorld()
  18.         {
  19.             return "Hello World";
  20.         }
  21.         [WebMethod(Description = "计算两个数的和")]
  22.         [IpFilter("127.0.0.1", "192.168.1.1")] // 此处为该方法的IP白名单,加上web.config中的白名单共同生效
  23.         public int Add(int a, int b)
  24.         {
  25.             return a + b;
  26.         }
  27.     }
  28. }
复制代码


四、IP拦截器实现总结

通过上述步骤,我们乐成实现了在 ASP.NET WebForms 中基于IP地址的访问控制。我们分别使用自界说的 SoapExtension 和 IHttpModule,实现了对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访问控制有所资助。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

祗疼妳一个

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表