当前位置: 代码网 > it编程>编程语言>Asp.net > C#进阶-基于.NET Framework 4.x框架实现ASP.NET WebForms项目IP拦截器

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

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

在这篇文章中,我们将探讨如何在 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 = "";
            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访问控制有所帮助。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com