取IP的函数有PageRequestUserHostAddress 简单好用但有时取不到真正IP 目前网上流行的所谓取真实IP地址的方法都有bug没有考虑到多层透明代理的情况 多数代码类似 string IpAddress = (HttpContextCurrentRequestServerVariables[HTTP_X_FORWARDED_FOR]!=null && HttpContextCurrentRequestServerVariables[HTTP_X_FORWARDED_FOR] !=StringEmpty) ?HttpContextCurrentRequestServerVariables[HTTP_X_FORWARDED_FOR] :HttpContextCurrentRequestServerVariables[REMOTE_ADDR]; 事实上上面的代码只试用与用户只使用了层代理如果用户有层层HTTP_X_FORWARDED_FOR 的值是本机真实IP层代理IP层代理IP 如果这个时候你的数据中保存IP字段的长度很小(个字节)数据库就报错了 实际应用中因为使用多层透明代理的情况比较少所以这种用户并不多 其他应用情况现在越来越多的网站使用了代理加速方式比如 新浪SOHU的新闻 都使用Squid做代理方式利用多台服务器分流Squid本身类似透明代理会发送HTTP_X_FORWARDED_FOR HTTP_X_FORWARDED_FOR 中包括客户的IP地址如果此时客户已经使用了一层透明代理那么程序取的 HTTP_X_FORWARDED_FOR 就包括两个IP地址(我遇到过个IP地址的情况个的未遇到过) 所以取真正IP地址的方式还应该判断 HTTP_X_FORWARDED_FOR 中是否有逗号或者长度是否超长(超过字节 xxxxxxxxxxxx) 所以代码应该如下 /**//// <summary> /// 取得客户端真实IP如果有代理则取第一个非内网地址 /// </summary> public static string IPAddress { get { string result = StringEmpty; result = HttpContextCurrentRequestServerVariables[HTTP_X_FORWARDED_FOR]; if(result!=null&&result!= StringEmpty) { //可能有代理 if(resultIndexOf()==) //没有肯定是非IPv格式 result = null; else { if(resultIndexOf()!=) { //有估计多个代理取第一个不是内网的IP result = resultReplace( )Replace(); string[] temparyip = resultSplit(;ToCharArray()); for(int i=;i<temparyipLength;i++) { if( TextIsIPAddress(temparyip[i]) && temparyip[i]Substring()!= && temparyip[i]Substring()!= && temparyip[i]Substring()!=) { return temparyip[i]; //找到不是内网的地址 } } } else if(TextIsIPAddress(result)) //代理即是IP格式 return result; else result = null; //代理中的内容 非IP取IP } } string IpAddress = (HttpContextCurrentRequestServerVariables[HTTP_X_FORWARDED_FOR]!=null && HttpContextCurrentRequestServerVariables[HTTP_X_FORWARDED_FOR] !=StringEmpty)?HttpContextCurrentRequestServerVariables[HTTP_X_FORWARDED_FOR]:HttpContextCurrentRequestServerVariables[REMOTE_ADDR]; if (null == result || result == StringEmpty) result = HttpContextCurrentRequestServerVariables[REMOTE_ADDR]; if (result == null || result == StringEmpty) result = HttpContextCurrentRequestUserHostAddress; return result; } } 取HTTP_X_FORWARDED_FOR 的弊端 HTTP_X_FORWARDED_FOR 是HTTP协议中头的一部分不影响TCP的通讯也就是说实际上客户端可以发送任意内容的 HTTP_X_FORWARDED_FOR以就是伪造IP最简单的是WEB程序的IP记录本来是要记录真实IP的反而被黑客欺骗当你的应用程序记录客户的访问IP拒绝或允许部分IP的访问错误日志 都会出错甚至误杀 因此必要的安全日志应该记录 完整的 HTTP_X_FORWARDED_FOR (至少给数据库中的字段分配 *+ 个字节以记录至少个IP) 和 REMOTE_ADDR对 HTTP_X_FORWARDED_FOR 的IP格式检查也是不可少的 附:(Text是我自定义的一个类IsIPAddress是其中的一个判断是否是IP地址格式的方法) #region bool IsIPAddress(str) 判断是否是IP格式 /**//// <summary> /// 判断是否是IP地址格式 /// </summary> /// <param name=str>待判断的IP地址</param> /// <returns>true or false</returns> public static bool IsIPAddress(string str) { if(str==null||str==stringEmpty||strLength<||strLength>) return false; string regformat = @^\d{}[\]\d{}[\]\d{}[\]\d{}$; Regex regex = new Regex(regformatRegexOptionsIgnoreCase ); return regexIsMatch(str); } #endregion |