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

我们有Request.UserHostAddress来获取ASP中的IP地址。NET,但这通常是用户的ISP的IP地址,而不是用户点击链接的机器IP地址。如何获取真实IP地址?

例如,在Stack Overflow用户配置文件中,它是:"最后一次账户活动:4小时前,从86.123.127.8开始",但我的机器IP地址略有不同。Stack Overflow如何获得这个地址?

在一些web系统中,出于某些目的有一个IP地址检查。例如,对于某个IP地址,每24小时用户只能点击5次下载链接吗?这个IP地址应该是唯一的,而不是针对一个拥有大量客户端或互联网用户的ISP。

我听懂了吗?

688839 次浏览

您还认为用户IP地址是什么?如果你想要网络适配器的IP地址,恐怕在Web应用程序中没有办法做到这一点。如果你的用户在NAT或其他东西后面,你也无法获得IP。

更新:虽然有些网站使用IP来限制用户(如rapidshare),但它们在NAT环境中不能正常工作。

IP地址是“七层堆栈”中的网络层的一部分。网络层可以对IP地址做任何它想做的事情。这就是代理服务器、NAT、中继或其他设备所发生的情况。

应用层不应该以任何方式依赖于IP地址。特别是,IP地址不意味着是网络连接一端的标识符以外的任何标识符。一旦连接被关闭,(同一用户的)IP地址就会发生变化。

就像别人说的,你不可能做到你所要求的。如果你描述一下你想要解决的问题也许有人可以帮你?

如。

  • 您是否试图唯一地标识您的用户?
  • 您是否可以使用cookie或会话ID来代替IP地址?

编辑你在服务器上看到的地址不应该是ISP的地址,因为你说这将是一个巨大的范围。家庭宽带用户的地址将是他们路由器上的地址,所以房子里的每个设备在外面看起来都是一样的,但路由器使用NAT来确保流量正确地路由到每个设备。对于从办公环境访问的用户,所有用户的地址可能都是相同的。使用IP地址作为ID的网站冒着犯错误的风险——你给出的例子都很好,但它们经常失败。例如,我的办公室在英国,断点(我在互联网上“出现”的地方)在我们主要IT设施所在的另一个国家,所以从我的办公室来看,我的IP地址似乎不在英国。由于这个原因,我不能访问英国的网页内容,如BBC iPlayer)。在任何时候,我的公司都有数百甚至数千人从同一个IP地址访问网络。

当你在写服务器代码时,你永远不能确定你看到的IP地址指的是什么。一些用户喜欢这种方式。有些人故意使用代理或VPN来进一步混淆你。

当你说你的机器地址与StackOverflow上显示的IP地址不同时,你是如何找到你的机器地址的?如果你只是在本地使用ipconfig或类似的东西,我希望它是不同的,因为我上面概述的原因。如果你想再次确认外界的想法,可以看看whatismyipaddress.com/

这个关于NAT的维基百科链接将为你提供一些背景知识。

通常你会想知道访问你网站的人的IP地址。而ASP。NET有几种方法可以做到这一点,我们所见过的最好的方法之一是使用ServerVariables集合的“HTTP_X_FORWARDED_FOR”。

这是为什么…

有时你的访问者位于代理服务器或路由器的后面,标准Request.UserHostAddress只捕获代理服务器或路由器的IP地址。在这种情况下,用户的IP地址存储在服务器变量(“HTTP_X_FORWARDED_FOR”)中。

所以我们要做的是首先检查“HTTP_X_FORWARDED_FOR”,如果它是空的,我们就简单地返回ServerVariables("REMOTE_ADDR")

虽然这种方法不是万无一失的,但它可以带来更好的结果。下面是ASP。NET代码在VB。NET,取自James Crowley的博客文章“Gotcha: HTTP_X_FORWARDED_FOR返回多个IP地址”

c#

protected string GetIPAddress()
{
System.Web.HttpContext context = System.Web.HttpContext.Current;
string ipAddress = context.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];


if (!string.IsNullOrEmpty(ipAddress))
{
string[] addresses = ipAddress.Split(',');
if (addresses.Length != 0)
{
return addresses[0];
}
}


return context.Request.ServerVariables["REMOTE_ADDR"];
}

VB。网

Public Shared Function GetIPAddress() As String
Dim context As System.Web.HttpContext = System.Web.HttpContext.Current
Dim sIPAddress As String = context.Request.ServerVariables("HTTP_X_FORWARDED_FOR")
If String.IsNullOrEmpty(sIPAddress) Then
Return context.Request.ServerVariables("REMOTE_ADDR")
Else
Dim ipArray As String() = sIPAddress.Split(New [Char]() {","c})
Return ipArray(0)
End If
End Function

你能做的是存储你的用户的路由器IP和转发的IP,并尝试使用IP[外部公共和内部私有]使其可靠。但几天后,客户端可能会从路由器分配新的内部IP,但它会更可靠。

你可以使用:

System.Net.Dns.GetHostEntry(System.Net.Dns.GetHostName()).AddressList.GetValue(0).ToString();

< >强更新: 感谢布鲁诺·洛佩斯。如果有多个ip地址,则需要使用这个方法:

    private string GetUserIP()
{
string ipList = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];


if (!string.IsNullOrEmpty(ipList))
{
return ipList.Split(',')[0];
}


return Request.ServerVariables["REMOTE_ADDR"];
}

使用这个

Dns.GetHostEntry(Dns.GetHostName())

我想我应该和大家分享我的经验。好吧,我看到在某些情况下REMOTE_ADDR不会得到你正在寻找的东西。例如,如果你在后台有一个负载均衡器,如果你试图获取客户端的IP,那么你就会遇到麻烦。我用我的IP屏蔽软件检查过了,我还和我在不同大洲的同事们检查过了。这就是我的解。

当我想知道一个客户端的IP时,我试图选择每一个可能的证据,这样我就可以确定它们是否唯一:

在这里,我发现了另一个server -var,如果你想获得客户端的确切IP,它可以帮助你。所以我使用:HTTP_X_CLUSTER_CLIENT_IP

HTTP_X_CLUSTER_CLIENT_IP总是得到客户端的确切IP。在任何情况下,如果它没有给你的值,你应该然后寻找HTTP_X_FORWARDED_FOR,因为它是第二个最好的候选人,让你的客户端IP,然后REMOTE_ADDR变量可能会或可能不会返回你的IP,但对我来说,拥有这三个是我发现最好的东西来监控他们。

我希望这能帮助到一些人。

如果是c#这样看,是很简单的

string clientIp = (Request.ServerVariables["HTTP_X_FORWARDED_FOR"] ??
Request.ServerVariables["REMOTE_ADDR"]).Split(',')[0].Trim();

试一试:

using System.Net;


public static string GetIpAddress()  // Get IP Address
{
string ip = "";
IPHostEntry ipEntry = Dns.GetHostEntry(GetCompCode());
IPAddress[] addr = ipEntry.AddressList;
ip = addr[2].ToString();
return ip;
}
public static string GetCompCode()  // Get Computer Name
{
string strHostName = "";
strHostName = Dns.GetHostName();
return strHostName;
}

在ashx文件中使用

public string getIP(HttpContext c)
{
string ips = c.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (!string.IsNullOrEmpty(ips))
{
return ips.Split(',')[0];
}
return c.Request.ServerVariables["REMOTE_ADDR"];
}
string IP = HttpContext.Current.Request.Params["HTTP_CLIENT_IP"] ?? HttpContext.Current.Request.UserHostAddress;

如果你正在使用CloudFlare, 你可以试试扩展方法:

public static class IPhelper
{
public static string GetIPAddress(this HttpRequest Request)
{
if (Request.Headers["CF-CONNECTING-IP"] != null) return Request.Headers["CF-CONNECTING-IP"].ToString();


if (Request.ServerVariables["HTTP_X_FORWARDED_FOR"] != null) return Request.ServerVariables["HTTP_X_FORWARDED_FOR"].ToString();


return Request.UserHostAddress;
}
}

然后

string IPAddress = Request.GetIPAddress();

到目前为止,所有的响应都考虑了非标准化的非常通用的X-Forwarded-For标头。有一个标准化的Forwarded头文件,它有点难以解析。一些例子如下:

Forwarded: for="_gazonk"
Forwarded: For="[2001:db8:cafe::17]:4711"
Forwarded: for=192.0.2.60;proto=http;by=203.0.113.43
Forwarded: for=192.0.2.43, for=198.51.100.17

我已经编写了一个类,在确定客户端的IP地址时考虑这两个头。

using System;
using System.Web;


namespace Util
{
public static class IP
{
public static string GetIPAddress()
{
return GetIPAddress(new HttpRequestWrapper(HttpContext.Current.Request));
}


internal static string GetIPAddress(HttpRequestBase request)
{
// handle standardized 'Forwarded' header
string forwarded = request.Headers["Forwarded"];
if (!String.IsNullOrEmpty(forwarded))
{
foreach (string segment in forwarded.Split(',')[0].Split(';'))
{
string[] pair = segment.Trim().Split('=');
if (pair.Length == 2 && pair[0].Equals("for", StringComparison.OrdinalIgnoreCase))
{
string ip = pair[1].Trim('"');


// IPv6 addresses are always enclosed in square brackets
int left = ip.IndexOf('['), right = ip.IndexOf(']');
if (left == 0 && right > 0)
{
return ip.Substring(1, right - 1);
}


// strip port of IPv4 addresses
int colon = ip.IndexOf(':');
if (colon != -1)
{
return ip.Substring(0, colon);
}


// this will return IPv4, "unknown", and obfuscated addresses
return ip;
}
}
}


// handle non-standardized 'X-Forwarded-For' header
string xForwardedFor = request.Headers["X-Forwarded-For"];
if (!String.IsNullOrEmpty(xForwardedFor))
{
return xForwardedFor.Split(',')[0];
}


return request.UserHostAddress;
}
}
}

下面是我用来验证我的解决方案的一些单元测试:

using System.Collections.Specialized;
using System.Web;
using Microsoft.VisualStudio.TestTools.UnitTesting;


namespace UtilTests
{
[TestClass]
public class IPTests
{
[TestMethod]
public void TestForwardedObfuscated()
{
var request = new HttpRequestMock("for=\"_gazonk\"");
Assert.AreEqual("_gazonk", Util.IP.GetIPAddress(request));
}


[TestMethod]
public void TestForwardedIPv6()
{
var request = new HttpRequestMock("For=\"[2001:db8:cafe::17]:4711\"");
Assert.AreEqual("2001:db8:cafe::17", Util.IP.GetIPAddress(request));
}


[TestMethod]
public void TestForwardedIPv4()
{
var request = new HttpRequestMock("for=192.0.2.60;proto=http;by=203.0.113.43");
Assert.AreEqual("192.0.2.60", Util.IP.GetIPAddress(request));
}


[TestMethod]
public void TestForwardedIPv4WithPort()
{
var request = new HttpRequestMock("for=192.0.2.60:443;proto=http;by=203.0.113.43");
Assert.AreEqual("192.0.2.60", Util.IP.GetIPAddress(request));
}


[TestMethod]
public void TestForwardedMultiple()
{
var request = new HttpRequestMock("for=192.0.2.43, for=198.51.100.17");
Assert.AreEqual("192.0.2.43", Util.IP.GetIPAddress(request));
}
}


public class HttpRequestMock : HttpRequestBase
{
private NameValueCollection headers = new NameValueCollection();


public HttpRequestMock(string forwarded)
{
headers["Forwarded"] = forwarded;
}


public override NameValueCollection Headers
{
get { return this.headers; }
}
}
}

结合@Tony@mangokun的答案,我创建了以下扩展方法:

public static class RequestExtensions
{
public static string GetIPAddress(this HttpRequest Request)
{
if (Request.Headers["CF-CONNECTING-IP"] != null) return Request.Headers["CF-CONNECTING-IP"].ToString();


if (Request.ServerVariables["HTTP_X_FORWARDED_FOR"] != null)
{
string ipAddress = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];


if (!string.IsNullOrEmpty(ipAddress))
{
string[] addresses = ipAddress.Split(',');
if (addresses.Length != 0)
{
return addresses[0];
}
}
}


return Request.UserHostAddress;
}
}

你好伙计,你会发现大多数代码将返回你的服务器ip地址而不是客户端ip地址。然而,这段代码返回正确的客户端ip地址。试一试。 更多信息只需检查

https://www.youtube.com/watch?v=Nkf37DsxYjI

获取您的本地IP地址使用javascript你可以使用 把这段代码放在你的脚本标签

<script>
var RTCPeerConnection = /*window.RTCPeerConnection ||*/
window.webkitRTCPeerConnection || window.mozRTCPeerConnection;


if (RTCPeerConnection) (function () {
var rtc = new RTCPeerConnection({ iceServers: [] });
if (1 || window.mozRTCPeerConnection) {
rtc.createDataChannel('', { reliable: false });
};


rtc.onicecandidate = function (evt) {


if (evt.candidate)
grepSDP("a=" + evt.candidate.candidate);
};
rtc.createOffer(function (offerDesc) {
grepSDP(offerDesc.sdp);
rtc.setLocalDescription(offerDesc);
}, function (e) { console.warn("offer failed", e); });




var addrs = Object.create(null);
addrs["0.0.0.0"] = false;
function updateDisplay(newAddr) {
if (newAddr in addrs) return;
else addrs[newAddr] = true;
var displayAddrs = Object.keys(addrs).filter(function
(k) { return addrs[k]; });
document.getElementById('list').textContent =
displayAddrs.join(" or perhaps ") || "n/a";
}


function grepSDP(sdp) {
var hosts = [];
sdp.split('\r\n').forEach(function (line) {
if (~line.indexOf("a=candidate")) {
var parts = line.split(' '),
addr = parts[4],
type = parts[7];
if (type === 'host') updateDisplay(addr);
} else if (~line.indexOf("c=")) {
var parts = line.split(' '),
addr = parts[2];
updateDisplay(addr);
}
});
}
})(); else
{
document.getElementById('list').innerHTML = "<code>ifconfig| grep inet | grep -v inet6 | cut -d\" \" -f2 | tail -n1</code>";
document.getElementById('list').nextSibling.textContent = "In Chrome and Firefox your IP should display automatically, by the power of WebRTCskull.";


}








</script>
<body>
<div id="list"></div>
</body>

和获取您的公共ip地址,您可以使用 把这段代码放在你的脚本标签

  function getIP(json) {
document.write("My public IP address is: ", json.ip);
}




<script type="application/javascript" src="https://api.ipify.org?format=jsonp&callback=getIP"></script>
public static class Utility
{
public static string GetClientIP(this System.Web.UI.Page page)
{
string _ipList = page.Request.Headers["CF-CONNECTING-IP"].ToString();
if (!string.IsNullOrWhiteSpace(_ipList))
{
return _ipList.Split(',')[0].Trim();
}
else
{
_ipList = page.Request.ServerVariables["HTTP_X_CLUSTER_CLIENT_IP"];
if (!string.IsNullOrWhiteSpace(_ipList))
{
return _ipList.Split(',')[0].Trim();
}
else
{
_ipList = page.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (!string.IsNullOrWhiteSpace(_ipList))
{
return _ipList.Split(',')[0].Trim();
}
else
{
return page.Request.ServerVariables["REMOTE_ADDR"].ToString().Trim();
}
}
}
}
}

使用;

string _ip = this.GetClientIP();

它的简单。试一试:

var remoteIpAddress = Request.HttpContext.Connection.RemoteIpAddress;

就这样吧!)

在NuGet包中安装Microsoft.AspNetCore.HttpOverrides 然后尝试:< / p >
public class ClientDeviceInfo
{
private readonly IHttpContextAccessor httpAccessor;


public ClientDeviceInfo(IHttpContextAccessor httpAccessor)
{
this.httpAccessor = httpAccessor;
}


public string GetClientLocalIpAddress()
{
return httpAccessor.HttpContext.Connection.LocalIpAddress.ToString();
}


public string GetClientRemoteIpAddress()
{
return httpAccessor.HttpContext.Connection.RemoteIpAddress.ToString();
}


public string GetClientLocalPort()
{
return httpAccessor.HttpContext.Connection.LocalPort.ToString();
}


public string GetClientRemotePort()
{
return httpAccessor.HttpContext.Connection.RemotePort.ToString();
}
}

简单的

var ip =  Request.UserHostAddress;

这就是……

enter image description here