如何在ASP.NET MVC中获取客户端的IP地址?

如何在ASP.NET MVC中获取客户端的IP地址?I’mtotallynewtotheASP.NETMVCstack,andIwaswonderingwhathappenedtothesimplePageobje

大家好,又见面了,我是你们的朋友全栈君。

本文翻译自:How can I get the client’s IP address in ASP.NET MVC?

I’m totally new to the ASP.NET MVC stack, and I was wondering what happened to the simple Page object and the Request ServerVariables object? 我是ASP.NET MVC堆栈的新手,我想知道简单的Page对象和Request ServerVariables对象发生了什么?

Basically, I want to to pull out the client PC’s IP address, but I fail to understand how the current MVC structure has changed all of this. 基本上,我想提取客户端PC的IP地址,但我无法理解当前的MVC结构如何改变了所有这些。

As far as I can understand, most of the variable objects has been replaced by the HttpRequest variants . 据我所知, 大多数变量对象已被HttpRequest变体所取代

Anybody care to share some resources? 有人关心分享一些资源吗? There is really a sea of stuff to learn in the ASP.NET MVC world. ASP.NET MVC世界中有很多东西要学习。 :) :)

For example, I have a static class with this current function. 例如,我有一个带有当前函数的静态类。 How do I get the same result using ASP.NET MVC? 如何使用ASP.NET MVC获得相同的结果?

public static int getCountry(Page page)
{
    return getCountryFromIP(getIPAddress(page));
}

public static string getIPAddress(Page page)
{
    string szRemoteAddr = page.Request.ServerVariables["REMOTE_ADDR"];
    string szXForwardedFor = page.Request.ServerVariables["X_FORWARDED_FOR"];
    string szIP = "";

    if (szXForwardedFor == null)
    {
        szIP = szRemoteAddr;
    }
    else
    {
        szIP = szXForwardedFor;

        if (szIP.IndexOf(",") > 0)
        {
            string [] arIPs = szIP.Split(',');

            foreach (string item in arIPs)
            {
                if (!isPrivateIP(item))
                {
                    return item;
                }
            }
        }
    }
    return szIP;
}

And how do I call this function from the controller page? 如何从控制器页面调用此功能?


#1楼

参考:https://stackoom.com/question/AoWW/如何在ASP-NET-MVC中获取客户端的IP地址


#2楼

A lot of the code here was very helpful, but I cleaned it up for my purposes and added some tests. 这里的很多代码都非常有用,但我为了我的目的清理了它并添加了一些测试。 Here’s what I ended up with: 这是我最终得到的:

using System;
using System.Linq;
using System.Net;
using System.Web;

public class RequestHelpers
{
    public static string GetClientIpAddress(HttpRequestBase request)
    {
        try
        {
            var userHostAddress = request.UserHostAddress;

            // Attempt to parse.  If it fails, we catch below and return "0.0.0.0"
            // Could use TryParse instead, but I wanted to catch all exceptions
            IPAddress.Parse(userHostAddress);

            var xForwardedFor = request.ServerVariables["X_FORWARDED_FOR"];

            if (string.IsNullOrEmpty(xForwardedFor))
                return userHostAddress;

            // Get a list of public ip addresses in the X_FORWARDED_FOR variable
            var publicForwardingIps = xForwardedFor.Split(',').Where(ip => !IsPrivateIpAddress(ip)).ToList();

            // If we found any, return the last one, otherwise return the user host address
            return publicForwardingIps.Any() ? publicForwardingIps.Last() : userHostAddress;
        }
        catch (Exception)
        {
            // Always return all zeroes for any failure (my calling code expects it)
            return "0.0.0.0";
        }
    }

    private static bool IsPrivateIpAddress(string ipAddress)
    {
        // http://en.wikipedia.org/wiki/Private_network
        // Private IP Addresses are: 
        //  24-bit block: 10.0.0.0 through 10.255.255.255
        //  20-bit block: 172.16.0.0 through 172.31.255.255
        //  16-bit block: 192.168.0.0 through 192.168.255.255
        //  Link-local addresses: 169.254.0.0 through 169.254.255.255 (http://en.wikipedia.org/wiki/Link-local_address)

        var ip = IPAddress.Parse(ipAddress);
        var octets = ip.GetAddressBytes();

        var is24BitBlock = octets[0] == 10;
        if (is24BitBlock) return true; // Return to prevent further processing

        var is20BitBlock = octets[0] == 172 && octets[1] >= 16 && octets[1] <= 31;
        if (is20BitBlock) return true; // Return to prevent further processing

        var is16BitBlock = octets[0] == 192 && octets[1] == 168;
        if (is16BitBlock) return true; // Return to prevent further processing

        var isLinkLocalAddress = octets[0] == 169 && octets[1] == 254;
        return isLinkLocalAddress;
    }
}

And here are some NUnit tests against that code (I’m using Rhino Mocks to mock the HttpRequestBase, which is the M<HttpRequestBase> call below): 以下是针对该代码的一些NUnit测试(我使用Rhino Mocks来模拟HttpRequestBase,这是下面的M <HttpRequestBase>调用):

using System.Web;
using NUnit.Framework;
using Rhino.Mocks;
using Should;

[TestFixture]
public class HelpersTests : TestBase
{
    HttpRequestBase _httpRequest;

    private const string XForwardedFor = "X_FORWARDED_FOR";
    private const string MalformedIpAddress = "MALFORMED";
    private const string DefaultIpAddress = "0.0.0.0";
    private const string GoogleIpAddress = "74.125.224.224";
    private const string MicrosoftIpAddress = "65.55.58.201";
    private const string Private24Bit = "10.0.0.0";
    private const string Private20Bit = "172.16.0.0";
    private const string Private16Bit = "192.168.0.0";
    private const string PrivateLinkLocal = "169.254.0.0";

    [SetUp]
    public void Setup()
    {
        _httpRequest = M<HttpRequestBase>();
    }

    [TearDown]
    public void Teardown()
    {
        _httpRequest = null;
    }

    [Test]
    public void PublicIpAndNullXForwardedFor_Returns_CorrectIp()
    {
        // Arrange
        _httpRequest.Stub(x => x.UserHostAddress).Return(GoogleIpAddress);
        _httpRequest.Stub(x => x.ServerVariables[XForwardedFor]).Return(null);

        // Act
        var ip = RequestHelpers.GetClientIpAddress(_httpRequest);

        // Assert
        ip.ShouldEqual(GoogleIpAddress);
    }

    [Test]
    public void PublicIpAndEmptyXForwardedFor_Returns_CorrectIp()
    {
        // Arrange
        _httpRequest.Stub(x => x.UserHostAddress).Return(GoogleIpAddress);
        _httpRequest.Stub(x => x.ServerVariables[XForwardedFor]).Return(string.Empty);

        // Act
        var ip = RequestHelpers.GetClientIpAddress(_httpRequest);

        // Assert
        ip.ShouldEqual(GoogleIpAddress);
    }

    [Test]
    public void MalformedUserHostAddress_Returns_DefaultIpAddress()
    {
        // Arrange
        _httpRequest.Stub(x => x.UserHostAddress).Return(MalformedIpAddress);
        _httpRequest.Stub(x => x.ServerVariables[XForwardedFor]).Return(null);

        // Act
        var ip = RequestHelpers.GetClientIpAddress(_httpRequest);

        // Assert
        ip.ShouldEqual(DefaultIpAddress);
    }

    [Test]
    public void MalformedXForwardedFor_Returns_DefaultIpAddress()
    {
        // Arrange
        _httpRequest.Stub(x => x.UserHostAddress).Return(GoogleIpAddress);
        _httpRequest.Stub(x => x.ServerVariables[XForwardedFor]).Return(MalformedIpAddress);

        // Act
        var ip = RequestHelpers.GetClientIpAddress(_httpRequest);

        // Assert
        ip.ShouldEqual(DefaultIpAddress);
    }

    [Test]
    public void SingleValidPublicXForwardedFor_Returns_XForwardedFor()
    {
        // Arrange
        _httpRequest.Stub(x => x.UserHostAddress).Return(GoogleIpAddress);
        _httpRequest.Stub(x => x.ServerVariables[XForwardedFor]).Return(MicrosoftIpAddress);

        // Act
        var ip = RequestHelpers.GetClientIpAddress(_httpRequest);

        // Assert
        ip.ShouldEqual(MicrosoftIpAddress);
    }

    [Test]
    public void MultipleValidPublicXForwardedFor_Returns_LastXForwardedFor()
    {
        // Arrange
        _httpRequest.Stub(x => x.UserHostAddress).Return(GoogleIpAddress);
        _httpRequest.Stub(x => x.ServerVariables[XForwardedFor]).Return(GoogleIpAddress + "," + MicrosoftIpAddress);

        // Act
        var ip = RequestHelpers.GetClientIpAddress(_httpRequest);

        // Assert
        ip.ShouldEqual(MicrosoftIpAddress);
    }

    [Test]
    public void SinglePrivateXForwardedFor_Returns_UserHostAddress()
    {
        // Arrange
        _httpRequest.Stub(x => x.UserHostAddress).Return(GoogleIpAddress);
        _httpRequest.Stub(x => x.ServerVariables[XForwardedFor]).Return(Private24Bit);

        // Act
        var ip = RequestHelpers.GetClientIpAddress(_httpRequest);

        // Assert
        ip.ShouldEqual(GoogleIpAddress);
    }

    [Test]
    public void MultiplePrivateXForwardedFor_Returns_UserHostAddress()
    {
        // Arrange
        _httpRequest.Stub(x => x.UserHostAddress).Return(GoogleIpAddress);
        const string privateIpList = Private24Bit + "," + Private20Bit + "," + Private16Bit + "," + PrivateLinkLocal;
        _httpRequest.Stub(x => x.ServerVariables[XForwardedFor]).Return(privateIpList);

        // Act
        var ip = RequestHelpers.GetClientIpAddress(_httpRequest);

        // Assert
        ip.ShouldEqual(GoogleIpAddress);
    }

    [Test]
    public void MultiplePublicXForwardedForWithPrivateLast_Returns_LastPublic()
    {
        // Arrange
        _httpRequest.Stub(x => x.UserHostAddress).Return(GoogleIpAddress);
        const string privateIpList = Private24Bit + "," + Private20Bit + "," + MicrosoftIpAddress + "," + PrivateLinkLocal;
        _httpRequest.Stub(x => x.ServerVariables[XForwardedFor]).Return(privateIpList);

        // Act
        var ip = RequestHelpers.GetClientIpAddress(_httpRequest);

        // Assert
        ip.ShouldEqual(MicrosoftIpAddress);
    }
}

#3楼

Request.ServerVariables["REMOTE_ADDR"] should work – either directly in a view or in the controller action method body (Request is a property of Controller class in MVC, not Page). Request.ServerVariables["REMOTE_ADDR"]应该可以工作 – 直接在视图中或在控制器动作方法体中(Request是MVC中Controller类的属性,而不是Page)。

It is working.. but you have to publish on a real IIS not the virtual one. 它工作..但你必须在真正的IIS上发布而不是虚拟的。


#4楼

How I account for my site being behind an Amazon AWS Elastic Load Balancer (ELB): 我如何说明我的网站背后是亚马逊AWS Elastic Load Balancer(ELB):

public class GetPublicIp {

    /// <summary>
    /// account for possbility of ELB sheilding the public IP address
    /// </summary>
    /// <returns></returns>
    public static string Execute() {
        try {
            Console.WriteLine(string.Join("|", new List<object> {
                    HttpContext.Current.Request.UserHostAddress,
                    HttpContext.Current.Request.Headers["X-Forwarded-For"],
                    HttpContext.Current.Request.Headers["REMOTE_ADDR"]
                })
            );

            var ip = HttpContext.Current.Request.UserHostAddress;
            if (HttpContext.Current.Request.Headers["X-Forwarded-For"] != null) {
                ip = HttpContext.Current.Request.Headers["X-Forwarded-For"];
                Console.WriteLine(ip + "|X-Forwarded-For");
            }
            else if (HttpContext.Current.Request.Headers["REMOTE_ADDR"] != null) {
                ip = HttpContext.Current.Request.Headers["REMOTE_ADDR"];
                Console.WriteLine(ip + "|REMOTE_ADDR");
            }
            return ip;
        }
        catch (Exception ex) {
            Console.Error.WriteLine(ex.Message);
        }
        return null;
    }
}

#5楼

The simple answer is to use the HttpRequest.UserHostAddress property . 简单的答案是使用HttpRequest.UserHostAddress属性

Example: From within a Controller: 示例:在Controller中:

using System;
using System.Web.Mvc;

namespace Mvc.Controllers
{
    public class HomeController : ClientController
    {
        public ActionResult Index()
        {
            string ip = Request.UserHostAddress;

            ...
        }
    }
}

Example: From within a helper class: 示例:从辅助类中:

using System.Web;

namespace Mvc.Helpers
{
    public static class HelperClass
    {
        public static string GetIPHelper()
        {
            string ip = HttpContext.Current.Request.UserHostAddress;
            ..
        }
    }
}

BUT, if the request has been passed on by one, or more, proxy servers then the IP address returned by HttpRequest.UserHostAddress property will be the IP address of the last proxy server that relayed the request. 但是,如果请求已由一个或多个代理服务器传递,则HttpRequest.UserHostAddress属性返回的IP地址将是中继请求的最后一个代理服务器的IP地址。

Proxy servers MAY use the de facto standard of placing the client’s IP address in the X-Forwarded-For HTTP header. 代理服务器可以使用将客户端的IP地址放在X-Forwarded-For HTTP标头中的事实标准。 Aside from there is no guarantee that a request has a X-Forwarded-For header, there is also no guarantee that the X-Forwarded-For hasn’t been SPOOFED . 除了无法保证请求具有X-Forwarded-For标头之外,还无法保证X-Forwarded-For未被SPOOFED


Original Answer 原始答案

Request.UserHostAddress

The above code provides the Client’s IP address without resorting to looking up a collection. 上面的代码提供了客户端的IP地址,而无需查找集合。 The Request property is available within Controllers (or Views). Request属性在Controllers(或Views)中可用。 Therefore instead of passing a Page class to your function you can pass a Request object to get the same result: 因此,您可以传递一个Request对象来获取相同的结果,而不是将Page类传递给您的函数:

public static string getIPAddress(HttpRequestBase request)
{
    string szRemoteAddr = request.UserHostAddress;
    string szXForwardedFor = request.ServerVariables["X_FORWARDED_FOR"];
    string szIP = "";

    if (szXForwardedFor == null)
    {
        szIP = szRemoteAddr;
    }
    else
    {
        szIP = szXForwardedFor;
        if (szIP.IndexOf(",") > 0)
        {
            string [] arIPs = szIP.Split(',');

            foreach (string item in arIPs)
            {
                if (!isPrivateIP(item))
                {
                    return item;
                }
            }
        }
    }
    return szIP;
}

#6楼

In a class you might call it like this: 在课堂上你可以这样称呼它:

public static string GetIPAddress(HttpRequestBase request) 
{
    string ip;
    try
    {
        ip = request.ServerVariables["HTTP_X_FORWARDED_FOR"];
        if (!string.IsNullOrEmpty(ip))
        {
            if (ip.IndexOf(",") > 0)
            {
                string[] ipRange = ip.Split(',');
                int le = ipRange.Length - 1;
                ip = ipRange[le];
            }
        } else
        {
            ip = request.UserHostAddress;
        }
    } catch { ip = null; }

    return ip; 
}

I used this in a razor app with great results. 我在剃须刀应用程序中使用了这个,效果很好。

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

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/162906.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • SQL 分页查询 返回总条数

    SQL 分页查询 返回总条数分页查询返回总数SELECTSQL_CALC_FOUND_ROWS*FROMtbWHERExxxlimitM,N;SELECTFOUND_ROWS();

    2022年6月26日
    35
  • springboot和springmvc的区别

    springboot和springmvc的区别面试题:你知道springboot和springmvc的区别是什么?之前自己搭过springboot的相关项目,但是如何进行比较,从自我感觉来看就是使用springboot用起来几乎没有配置,个人搭的项目没有用到配置相关的内容。于是我就用了这个回答给面试官,可想而知,这种回答并不好。于是现在百度了相关文章,就把理解写成博客当做笔记。springmvc从两个方面…

    2022年6月10日
    36
  • 2021sublime4113 激活码-激活码分享

    (2021sublime4113 激活码)JetBrains旗下有多款编译器工具(如:IntelliJ、WebStorm、PyCharm等)在各编程领域几乎都占据了垄断地位。建立在开源IntelliJ平台之上,过去15年以来,JetBrains一直在不断发展和完善这个平台。这个平台可以针对您的开发工作流进行微调并且能够提供…

    2022年3月27日
    218
  • Automation服务器不能创建对象(金税盘)

    Automation服务器不能创建对象(金税盘)  1.安装防伪开票组件接口软件;  2.把接口的注册文件放到%防伪开票系统的安装目录%\BIN下  3.把%防伪开票系统的安装目录%\bin下的TaxCardX.dll文件复制至c:\windows\system32下  4.注册dll:在开始菜单中选择”运行”,输入”regsvr32TaxCardX.dll”5.  备注:此处电脑可能会提示不兼容,如:  …

    2022年6月1日
    32
  • 数电课设 八路抢答器设计详解

    数电课设 八路抢答器设计详解设计一个八路竞赛抢答器,可同时供八名选手或八个代表队参加比赛,他们的选号分别是1、2、3、4、5、6、7、8,各用一个抢答按钮,按钮的编号与选手的编号相对应,分别是S1、S2、S3、S4、S5、S6、S7、S8。给节目主持人设置一个控制开关,用来控制系统的清零(编号显示码管灭灯)和抢答器的开始(开始倒计时)。抢答器具有数据锁存和显示的功能。抢答开始后,若有选手按动抢答按钮,编号立即锁存,并在LED数码管上显示出选手的编号,同时扬声器给出音响提示。此外,要封锁输入电路,禁止其他选手抢答,优先抢答选手的编号

    2022年10月20日
    0
  • 黄聪:使用srvany.exe将任何程序作为Windows服务运行「建议收藏」

    黄聪:使用srvany.exe将任何程序作为Windows服务运行「建议收藏」srvany.exe是什么?srvany.exe是MicrosoftWindowsResourceKits工具集的一个实用的小工具,用于将任何EXE程序作为Windows服务运行。也就是说srvany只是其注册程序的服务外壳,这个特性对于我们来说非常实用,我们可以通过它让我们的程序以SYSTEM账户启动,或者实现随机器启动而自启动,也可以隐藏不必要的窗口,比如说控制台窗口等等。如何获…

    2022年6月4日
    25

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号