如何在单向ASMX Web服务中获取客户端IP地址

3
我有一个配置为单向的Web服务。或者说,SoapDocumentMethod属性有一个叫做"OneWay"的属性,设置为true。
我试图获取客户端请求的IP地址。我知道我得不到精确的IP地址,因为客户端可能在其他网络概念的后面。这不重要。我想获得调用服务的人的IP地址,所以如果那是某个前端服务器坐落在某个客户机上,那就没事了。
我尝试使用HttpContext,但似乎不起作用。如果我在与Web服务运行的同一台机器上访问我的Web服务,那么HttpContext会被填充,我可以获取IP地址。然而,任何对我的Web服务的外部使用,HttpContext都有些混乱。当尝试查找有关请求的信息时,它会抛出许多属性的异常。所以我无法获取客户端IP地址。如果启用服务的跟踪功能,那么它就开始工作了。但这只是暂时的解决办法。这不是可接受的解决办法。
那么...当您拥有单项Web服务时,最好的方法是什么?
我已经在这里看过了:http://msdn.microsoft.com/en-us/library/system.web.services.protocols.soapdocumentmethodattribute.oneway.aspx

请明确一下,这是一个旧版的ASP.Net Web服务应用程序吗? - bopapa_1979
是的,目前我的要求是使用 .net 3.0 或更早版本。 - OpenIdsAreDumb
回答已添加。希望能有所帮助,如果不行的话,可以自己发布网络方法,我会查看代码。 - bopapa_1979
1个回答

2

幸运的是,你有几个选择。

1)将IP地址作为参数传递--> 不建议使用。 2)为IP地址创建SOAP头并从客户端传递

我为选项2编写了一个快速示例。

首先,您需要扩展SoapHeader并创建一个类来传递IP地址。

using System.Web.Services.Protocols;

namespace SoapHeaders
{
    public class IpAddressHeader : SoapHeader
    {
        public string IpAddress;
    }
}

接下来,您需要使用该标头定义一个Web服务,并使用它的一个Web方法。
using System;
using System.IO;
using System.Web.Services.Protocols;
using System.Web.Services;
using SoapHeaders;

namespace WebService
{

    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]

    public class SoapHeaderService : System.Web.Services.WebService
    {
        public IpAddressHeader IpAddressHeader;

        [WebMethod]
        [SoapDocumentMethod(OneWay = true)]
        [SoapHeader("IpAddressHeader")]
        public void LogIpAddress()
        {
            var logFile = string.Format(@"C:\Logs\{0:yyyy-MM-dd HH.mm.ss.ffff}.log", DateTime.Now);

            string ipAddress;

            if (IpAddressHeader == null || string.IsNullOrEmpty(IpAddressHeader.IpAddress))
            {
                ipAddress = "?";
            }
            else
            {
                ipAddress = IpAddressHeader.IpAddress;
            }

            File.WriteAllText(logFile, string.Format("Client Address --> {0}", ipAddress));
        }
    }
}

最后,你需要一个客户端来使用服务并传递头信息。我只是制作了一个快速控制台应用程序,但实际上可以是任何东西:

using System.Net;
using ConsoleApplication.soapHeaderServices;

namespace ConsoleApplication
{
    class Program
    {

        static void Main(string[] args)
        {
            var ipAddressHeader = new IpAddressHeader();
            ipAddressHeader.IpAddress = GetIpAddress();

            var serviceClient = new SoapHeaderService();
            serviceClient.IpAddressHeaderValue = ipAddressHeader;

            serviceClient.LogIpAddress();
        }

        static string GetIpAddress()
        {
            var ipAddress = "?";
            var host = Dns.GetHostEntry(Dns.GetHostName());
            foreach (var address in host.AddressList)
            {
                if (address.AddressFamily.ToString() != "InterNetwork")
                {
                    continue;
                }

                ipAddress = address.ToString();
                break;
            }

            return ipAddress;
        }
    }
}

我在远程测试服务上部署了该服务,并从我的电脑调用它。 运行良好。 创建的日志文件内容为:客户端地址 -> 192.168.1.41。
希望这对您有所帮助!
编辑:请勿使用下面的代码。 它是错误的。 我将其留作不要这样做的示例。 单向操作中不可用服务器变量。
原始答案。 不要使用:请参阅我在EDIT之上更新的答案。
我刚在新的ASP.Net Web Service Application上进行了冒烟测试。 从我可以访问的每个端点都可以工作。
HttpRequest.UserHostAddress是获取客户端IP地址的文档方式。 如果这对您不起作用,我会寻找根本原因。
[WebMethod]
[SoapDocumentMethod(OneWay = true)]
public void Silent()
{
    var address = HttpContext.Current.Request.UserHostAddress;

    // Do something with address
    Trace.Write(address);
}

这与我正在运行的测试非常接近,当我尝试访问该属性时,除非我在同一台计算机上访问服务,否则会抛出异常。 - OpenIdsAreDumb
你能在这里发布你遇到的错误吗?此外,我建议将错误隔离到尽可能简单的场景中。Visual Studio --> 新建项目 --> 新建ASP.Net Web服务应用程序 --> 复制粘贴上述方法并尝试远程访问它。 - bopapa_1979
以上基本上就是我现在正在测试的。这是一个新项目。关于异常,属性Context.Request.UserHostAddress为null,我的代码因此崩溃。另外,属性Context.Request.ServerVariables由于参数异常而崩溃。无论您尝试访问ServierVariables的哪个属性(ServerVariables [0],ServierVariable.Count),都会抛出参数异常。对不起,我之前说错了。访问UserHostAddress不会引发异常。它只是空的。 - OpenIdsAreDumb
更新了我的答案。新版本可以工作。剩下的唯一问题是决定如何获取客户端IP地址。你可能想使用公共IP地址,而不是本地IP地址,出于某些原因。为此,请参考这里获取一些想法:https://dev59.com/DXA75IYBdhLWcg3wg5Zh#3253726 - bopapa_1979
这是一个替代解决方案。如果使用的方法标记为[SoapDocumentMethod(OneWay = true)],则无法实现您想要的功能。通过设计,在单向操作中不可用服务器变量。我认为这是你能找到的最佳可行解决方案。或者,如果您不需要它,可以删除属性。 - bopapa_1979

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接