(转)【ASP.NET开发】获取客户端IP地址 via C#
说明:本文中的内容是我综合博客园上的博文和MSDN讨论区的资料,再通过自己的实际测试而得来,属于自己原创的内容说实话很少,写这一篇是为了记录自己在项目中做过的事情,同时也想抛砖引玉。参考的博文及其作者在下文均有提及。待到自己以后对HTTP、TCP/IP等知识学深入了,一定再来这里深入讨论这个内容。
一、名词
首先说一下接下来要讲到的一些名词。
在Web开发中,我们大多都习惯使用HTTP请求头中的某些属性来获取客户端的IP地址,常见的属性是REMOTE_ADDR、HTTP_VIA和HTTP_X_FORWARDED_FOR。
这三个属性的含义,大概是如此:(摘自网上,欢迎指正)
REMOTE_ADDR:该属性的值是客户端跟服务器“握手”时候的IP。如果使用了“匿名代理”,REMOTE_ADDR将显示代理服务器的IP。
X-Forwarded-For:是用来识别通过HTTP代理或负载均衡方式连接到Web服务器的客户端最原始的IP地址的HTTP请求头字段。
XFF的有效性依赖于代理服务器提供的连接原始IP地址的真实性,因此, XFF的有效使用应该保证代理服务器是可信的, 比如可以通过建立可信服务器白名单的方式。
这一HTTP头一般格式如下:
X-Forwarded-For: client1, proxy1, proxy2
其中的值通过逗号+空格,把多个IP地址区分开, 最左边(client1)是最原始客户端的IP地址, 代理服务器每成功收到一个请求,就把请求来源IP地址添加到右边。 在上面这个例子中,这个请求成功通过了三台代理服务器:proxy1, proxy2 及 proxy3。请求由client1发出,到达了proxy3(proxy3可能是请求的终点)。请求刚从client1中发出时,XFF是空的,请求被发往proxy1;通过proxy1的时候,client1被添加到XFF中,之后请求被发往proxy2;通过proxy2的时候,proxy1被添加到XFF中,之后请求被发往proxy3;通过proxy3时,proxy2被添加到XFF中,之后请求的的去向不明,如果proxy3不是请求终点,请求会被继续转发。
鉴于伪造这一字段非常容易,应该谨慎使用X-Forwarded-For字段。正常情况下XFF中最后一个IP地址是最后一个代理服务器的IP地址, 这通常是一个比较可靠的信息来源。
(另附维基中对X-Forwarded-For的完整介绍:http://zh.wikipedia.org/wiki/X-Forwarded-For)
至于在使用这些属性的时候,属性的值是什么,网上查到一份这样的博文:获取用户IP地址的三个属性的区别(原作者不详)。
而在ASP.NET中,还可以通过另外一种方式获得客户端的IP地址,那就是通过Request对象中的UserHostAddress属性。在MSDN Library中,对这个属性是这样解释的:属性值是远程客户端的 IP 地址。
如果客户端使用了代理服务器,那么Request.UserHostAddress属性获得的就是代理服务器的IP地址。
二、方法
好了,讲了那么多概念性的东西,咱们来讲一下实现的方法。
网上大多数方法的思路是:如果有代理IP,则优先获取代理IP,否则获取连接客户端的IP;或者调转过来,先获取连接客户端的IP,如获取失败,则获取代理IP。
以下方法参考博文asp.net获取客户端IP (作者comeonfyz)
-----------------------------------------------------------------------------------------------------------

- /// <summary>
- /// 获取客户端IP地址
- /// </summary>
- /// <returns>若失败则返回回送地址</returns>
- public static string GetIP()
- {
- //如果客户端使用了代理服务器,则利用HTTP_X_FORWARDED_FOR找到客户端IP地址
- string userHostAddress = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"].ToString().Split(',')[0].Trim();
- //否则直接读取REMOTE_ADDR获取客户端IP地址
- if (string.IsNullOrEmpty(userHostAddress))
- {
- userHostAddress = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
- }
- //前两者均失败,则利用Request.UserHostAddress属性获取IP地址,但此时无法确定该IP是客户端IP还是代理IP
- if (string.IsNullOrEmpty(userHostAddress))
- {
- userHostAddress = HttpContext.Current.Request.UserHostAddress;
- }
- //最后判断获取是否成功,并检查IP地址的格式(检查其格式非常重要)
- if (!string.IsNullOrEmpty(userHostAddress) && IsIP(userHostAddress))
- {
- return userHostAddress;
- }
- return "127.0.0.1";
- }
- /// <summary>
- /// 检查IP地址格式
- /// </summary>
- /// <param name="ip"></param>
- /// <returns></returns>
- public static bool IsIP(string ip)
- {
- return System.Text.RegularExpressions.Regex.IsMatch(ip, @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$");
- }

-----------------------------------------------------------------------------------------------------------
但是这样做有一个很严重的缺陷,那就是如大牛Kingthy在其博文 使用HTTP_X_FORWARDED_FOR获取客户端IP的严重后果 中所说的,"HTTP_X_FORWARDED_FOR"这个值是通过获取HTTP头的"X_FORWARDED_FOR"属性取得的,恶意破坏者可以很轻松地伪造IP地址;而且上文特别提到过,XFF的有效性依赖于代理服务器提供的连接原始IP地址的真实性,因此, XFF的有效使用应该保证代理服务器是可信的。但是作为开发者,我们既不知道用户的IP地址的真实性,更是难以分辨代理服务器的可信性。
因此,综合各个方面的资料,我个人的想法与大牛Kingthy一样:无视代理。
-----------------------------------------------------------------------------------------------------------

- 1 /// <summary>
- 2 /// 获取客户端IP地址(无视代理)
- 3 /// </summary>
- 4 /// <returns>若失败则返回回送地址</returns>
- 5 public static string GetHostAddress()
- 6 {
- 7 string userHostAddress = HttpContext.Current.Request.UserHostAddress;
- 8
- 9 if (string.IsNullOrEmpty(userHostAddress))
- 10 {
- 11 userHostAddress = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
- 12 }
- 13
- 14 //最后判断获取是否成功,并检查IP地址的格式(检查其格式非常重要)
- 15 if (!string.IsNullOrEmpty(userHostAddress) && IsIP(userHostAddress))
- 16 {
- 17 return userHostAddress;
- 18 }
- 19 return "127.0.0.1";
- 20 }
- 21
- 22 /// <summary>
- 23 /// 检查IP地址格式
- 24 /// </summary>
- 25 /// <param name="ip"></param>
- 26 /// <returns></returns>
- 27 public static bool IsIP(string ip)
- 28 {
- 29 return System.Text.RegularExpressions.Regex.IsMatch(ip, @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$");
- 30 }

-----------------------------------------------------------------------------------------------------------
三、总结
无视代理服务器肯定不是最好的解决方案,如果项目需求明确说要客户端的真实地址,那肯定就不能无视代理服务器了。
另外,我也向Artech大牛请教过这方面的问题,他虽然对这些没有深入的研究,但是他也认为没有一种IP获取方式是完全值得信赖的,因为这是TCP/IP协议本身决定的。
附上Artech大牛给我的一份资料,分享分享。http://www.symantec.com/connect/articles/ip-spoofing-introduction
希望这篇博文能够抛砖引玉,欢迎批评和建议。
转自: http://www.cnblogs.com/stay-foolish/archive/2012/05/01/2475071.html
(转)【ASP.NET开发】获取客户端IP地址 via C#的更多相关文章
- ASP.NET Core获取客户端IP地址
1.在ConfigureServices注入IHttpContextAccessor // ASP.NET Core 2.1的注入方式 //services.AddHttpContextAccesso ...
- 再论 ASP.NET 中获取客户端IP地址
说到IP获取无非是我们常见的以下几种方式,但是具体获取的值具体区别在哪?网上不乏相关文章,说的也是很详细,但是真正使用起来,还有很多不太对的地方.IP在不同系统中,应用相当广泛,常见的日志记录.广告分 ...
- 获取客户端IP地址 via C#
获取客户端IP地址 via C# 说明:本文中的内容是我综合博客园上的博文和MSDN讨论区的资料,再通过自己的实际测试而得来,属于自己原创的内容说实话很少,写这一篇是为了记录自己在项目中做过的事情,同 ...
- 获取客户端IP地址定位城市信息
获取客户端IP地址定位城市信息 1.首先获取客户端的IP地址 function getIPaddress(){ $IPaddress=''; if (isset($_SERVER)){ if (iss ...
- C# WebApi 获取客户端ip地址
转自:http://www.cnblogs.com/weixing/p/5674078.html References required: HttpContextWrapper - System.We ...
- .net core webapi 后台获取客户端ip地址
Asp.Net Core2.0获取客户IP地址,及解决发布到Ubuntu服务器获取不到正确IP解决办法 1.获取客户端IP地址实现方法(扩展类) 1 using Microsoft.AspNetC ...
- 在Thinkphp3.2.3框架下实现自动获取客户端IP地址的get_client_ip()函数
在Thinkphp框架下使用get_client_ip()函数获取客户端IP地址十分方便: 一行代码便可以实现:$ip = get_client_ip(); 但当我们测试时会遇到后台获取的IP地址显示 ...
- JAVA获取客户端IP地址
在JSP里,获取客户端的IP地址的方法是:request.getRemoteAddr(),这种方法在大部分情况下都是有效的.但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实I ...
- php获取客户端ip地址
本文介绍一个,php获取客户端的IP地址的实例代码,有需要的朋友参考下吧. 获取客户端IP地址的代码,如下: 复制代码代码示例: <?php//取得客户端IP的函数function get_cl ...
随机推荐
- su terminal get around---docker root
su : must be run from a terminal After some googling, I found the solution from Tero's glob. If you ...
- scala 学习笔记
1.简洁 1.1.java的写法 class MyClass { private int index; private String name; public MyClass(int index, S ...
- There has been an error processing your request magento
如果使用magento的过程中,出现以下页面: 说明出现了错误,但是亲,不用紧张,请根据"Error record number:xxxxxxxxx"的数字在网站根目录下的var/ ...
- 我的工具箱之VNC
下载地址:http://pan.baidu.com/s/1bovEoZ9 这个工具可以连接到Linux并进行可视化操作. 如何搭建VNC环境请见 在centOS上安装VNC 2016年2月26日11: ...
- java.lang.IllegalArgumentException: No converter found for return value of type: class Person
在http://www.cnblogs.com/winner-0715/p/6033462.html我们讲到三个条件就能实现SpringMVC返回json的功能 但是按照这三个条件配置后,运行出现了错 ...
- iOS:集成ijkplayer视频直播
介绍: ijkplayer 是一款做视频直播的框架, 基于ffmpeg, 支持 Android 和 iOS, 网上也有很多集成说明, 但是个人觉得还是不够详细, 在这里详细的讲一下在 iOS 中如何集 ...
- JavaScript:JavaScript中常见获取对象元素的方法
介绍: javascript中常见的3种获取元素的方法,分别是通过元素ID.通过标签名字和通过类名字来获取 操作如下: 1.getElementById DOM提供了一个名为getElementByI ...
- 解决MyEclipse吃内存以及卡死的方法
前言:MyEclipse5.5 大小 139M:MyEclipse6.5 大小 451M:MyEclipse7.0 大小 649M!下载服务器又是国外的...下载速度累人也就罢了,只要你工作性能一流. ...
- linux:awk之RS、ORS与FS、OFS
awk之RS.ORS与FS.OFS RS:Record Separator,记录分隔符 ORS:Output Record Separate,输出当前记录分隔符 FS:Field Separato ...
- 项目管理利器——Maven
假设公司要开发一个新的Web项目,使用目前流行的struts2.spring.MyBatis进行新项目开发.那么接下来首先要进行的工作就是各个框架的jar包的下载.大家通常的做法是先到struts2的 ...