asp.net 取真实IP地址

限时加码!20+主流AI编程工具免费用 购周边加赠Coding Plan Lite,Claude Code、Cursor等即刻畅享,学习进阶更高效! 阅读详情
目前网上流行的所谓"取真实IP地址"的方法,都有bug,没有考虑到多层透明代理的情况。 
多数代码类似: 

string IpAddress = (HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]!=null 
&& HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] !=String.Empty) 
?HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] 
:HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"]; 


事实上,上面的代码只试用与用户只使用了1层代理,如果用户有2层,3层HTTP_X_FORWARDED_FOR 的值是:"本机真实IP,1层代理IP,2层代理IP,....." ,如果这个时候你的数据中保存IP字段的长度很小(15个字节),数据库就报错了。 

实际应用中,因为使用多层透明代理的情况比较少,所以这种用户并不多。 

其他应用情况,现在越来越多的网站使用了代理加速方式,比如 新浪、SOHU的新闻 都使用Squid做代理方式,利用多台服务器分流。Squid本身类似透明代理,会发送"HTTP_X_FORWARDED_FOR" ,HTTP_X_FORWARDED_FOR 中包括客户的IP地址,如果此时客户已经使用了一层透明代理,那么程序取的 "HTTP_X_FORWARDED_FOR" 就包括两个IP地址。(我遇到过3个IP地址的情况,4个的未遇到过) 

所以取"真正"IP地址的方式,还应该判断 "HTTP_X_FORWARDED_FOR" 中是否有","逗号,或者长度是否超长(超过15字节 xxx.xxx.xxx.xxx)。 

所以代码应该如下: 
  1. /// <summary>    
  2. /// 取得客户端真实IP。如果有代理则取第一个非内网地址    
  3. /// </summary>    
  4. public static string IPAddress    
  5.    
  6.     get    
  7.        
  8.         string result String.Empty;    
  9.         result HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];    
  10.         if(result!=null&&result!= String.Empty)    
  11.            
  12.             //可能有代理    
  13.             if(result.IndexOf(".")==-1)    //没有"."肯定是非IPv4格式    
  14.                 result null   
  15.             else    
  16.                
  17.                 if(result.IndexOf(",")!=-1)    
  18.                    
  19.                     //有",",估计多个代理。取第一个不是内网的IP。    
  20.                     result result.Replace(","").Replace(""","");    
  21.                     string[] temparyip result.Split(",;".ToCharArray());    
  22.                     for(int i=0;i<temparyip.Length;i++)    
  23.                        
  24.                         ifText.IsIPAddress(temparyip[i])    
  25.                             && temparyip[i].Substring(0,3)!="10."    
  26.                             && temparyip[i].Substring(0,7)!="192.168"    
  27.                             && temparyip[i].Substring(0,7)!="172.16."   
  28.                            
  29.                             return temparyip[i];    //找到不是内网的地址    
  30.                            
  31.                        
  32.                    
  33.                 else if(Text.IsIPAddress(result)) //代理即是IP格式    
  34.                     return result;    
  35.                 else    
  36.                     result null   //代理中的内容 非IP,取IP    
  37.                
  38.            
  39.         string IpAddress (HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]!=null && HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"!=String.Empty)?HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]:HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];    
  40.          if (null == result || result == String.Empty)    
  41.             result HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];    
  42.         if (result == null || result == String.Empty)    
  43.             result HttpContext.Current.Request.UserHostAddress;    
  44.         return result;    
  45.        
  46.    

 

取"HTTP_X_FORWARDED_FOR" 的弊端。 

HTTP_X_FORWARDED_FOR 是HTTP协议中头的一部分,不影响TCP的通讯。也就是说实际上客户端可以发送任意内容的 HTTP_X_FORWARDED_FOR,以就是伪造IP。最简单的是WEB程序的IP记录,本来是要记录真实IP的,反而被"黑客"欺骗。当你的应用程序记录客户的访问IP、拒绝或允许部分IP的访问、错误日志 都会出错,甚至误杀。 

因此必要的安全日志应该记录 完整的 "HTTP_X_FORWARDED_FOR" (至少给数据库中的字段分配 3*15+2 个字节,以记录至少3个IP) 和 "REMOTE_ADDR"。对 HTTP_X_FORWARDED_FOR 的IP格式检查也是不可少的。 

附:(Text是我自定义的一个类,IsIPAddress是其中的一个判断是否是IP地址格式的方法) 

 

  1. #region bool IsIPAddress(str1) 判断是否是IP格式    
  2. /// <summary>   
  3. /// 判断是否是IP地址格式 0.0.0.0   
  4. /// </summary>   
  5. /// <param name="str1">待判断的IP地址</param>   
  6. /// <returns>true or false</returns>   
  7. public static bool IsIPAddress(string str1)   
  8. {   
  9.     if(str1==null||str1==string.Empty||str1.Length<7||str1.Length>15) return false   
  10.     string regformat @"^\d{1,3}[\.]\d{1,3}[\.]\d{1,3}[\.]\d{1,3}$";   
  11.     Regex regex new Regex(regformat,RegexOptions.IgnoreCase );   
  12.     return regex.IsMatch(str1);   
  13.  
  14. #endregion  

使用实例:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using System.Management;//需要添加对类库System.Management.dll的引用
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using System.Text;
public partial class ip : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {

        try
        {
            
            string MoAddress = string.Empty;
            ManagementClass networkAdapter = new ManagementClass("Win32_NetworkAdapterConfiguration");
            ManagementObjectCollection adapterC = networkAdapter.GetInstances();
            foreach (ManagementObject m in adapterC)
            {
                if ((bool)m["IPEnabled"] == true)
                {
                    MoAddress = m["MacAddress"].ToString().Trim();
                    m.Dispose();
                }
            }
            Response.Write("您的ip:" + IPAddress + " 你的网卡:" + MoAddress);
        }
        catch (Exception err)
        {
            Response.Write(err.Message);
        }

    }

   
    /// <summary>    
    /// 取得客户端真实IP。如果有代理则取第一个非内网地址    
    /// </summary>    
    public static string IPAddress
    {
        get
        {
            string result = String.Empty;
            result = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
            if (result != null && result != String.Empty)
            {
                //可能有代理    
                if (result.IndexOf(".") == -1)    //没有"."肯定是非IPv4格式    
                    result = null;
                else
                {
                    if (result.IndexOf(",") != -1)
                    {
                        //有",",估计多个代理。取第一个不是内网的IP。    
                        result = result.Replace(" ", "").Replace(""", string.Empty);
                        string[] temparyip = result.Split(",;".ToCharArray());
                        for (int i = 0; i < temparyip.Length; i++)
                        {
                            if (IsIPAddress(temparyip[i])
                                && temparyip[i].Substring(0, 3) != "10."
                                && temparyip[i].Substring(0, 7) != "192.168"
                                && temparyip[i].Substring(0, 7) != "172.16.")
                            {
                                return temparyip[i];    //找到不是内网的地址    
                            }
                        }
                    }
                    else if (IsIPAddress(result)) //代理即是IP格式    
                        return result;
                    else
                        result = null;    //代理中的内容 非IP,取IP    
                }
            }
            string IpAddress = (HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] != null && HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] != String.Empty) ? HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] : HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
            if (string.IsNullOrEmpty(result))
                result = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
            if (string.IsNullOrEmpty(result))
                result = HttpContext.Current.Request.UserHostAddress;
            return result;
        }
    }
    #region bool IsIPAddress(str1) 判断是否是IP格式
   
    /// <summary>   
    /// 判断是否是IP地址格式 0.0.0.0   
    /// </summary>   
    /// <param name="str1">待判断的IP地址</param>   
    /// <returns>true or false</returns>   
    public static bool IsIPAddress(string str1)
    {
        if (str1 == null || str1 == string.Empty || str1.Length < 7 || str1.Length > 15) return false;
        string regformat = @"^\d{1,3}[\.]\d{1,3}[\.]\d{1,3}[\.]\d{1,3}$";
        Regex regex = new Regex(regformat, RegexOptions.IgnoreCase);
        return regex.IsMatch(str1);
    }
    #endregion  
}
Nginx+Docker部署模式下 asp.net core 获真实的客户端ip 场景 线上环境使用Nginx(安装在宿主机)+Docker进行部署,应用获客户端ip地址不正确,获客户端IP的代码为Request.HttpContext.Connection.RemoteIpAddress.MapToIPv4() 过程还原 搭建一个webapi示例环境 创建一个新项目 dotnet new webapi -o getRealClientIp 修改模板中的ValuesCon... 阅读详情

相关推荐

ASP.NET如何根据IP省市地址

 1、在网站的跟路径下面添加 QQWry.dat 文件,这个文件是IP数据库文件   2、添加以下一个类 IPScanner public class IPScanner { //私有成员#region 私有成员 private string dataPath; private string ip; p

whazhl的专栏 1996

真正的真实IP地址及利弊Asp.net

真正的真实IP地址及利弊Asp.net http://tech.aspxsoft.com/aspnet/2006-3-16/425.aspx 真正的真实IP地址及利弊Asp.net 作者: flowerbin 来源:网络 目前网上流行的所谓“真实ip地址”的方法,都有bug,没有考虑到多层透明代理的情况。 多数代码类似: string IpAddress = (HttpContext.Current.Request.ServerVariables["HTTP_X_

hl7777的专栏 359

ASP.NET中获客户端真实IP地址的完整实现方案

你以为加个白名单就够了?Too young.你以为学会了就够了吗?远远不够。真实的战场充满欺骗、伪装和不确定性。今天的最佳实践,明天可能就成了漏洞源头。所以,请记住这几条铁律:永远不要盲目信任任何头部字段建立自己的可信代理拓扑图每层都要有降级和监控合规不是附加项,而是设计前提最终你会发现,真正难的从来不是技术实现,而是在性能、准确性、安全性与合规性之间找到平衡点。而这,正是优秀工程师的价值所在。✨本文还有配套的精品资源,点击获

weixin_35756130的博客 496

RBTL方法在ZTF超新星光谱标准化中的应用与优化

光谱标准化是天体物理学数据处理中的关键技术,通过消除仪器响应差异和系统误差,确保观测数据的准确性和可比性。RBTL(Redshift-Based Template Learning)方法通过红移校正与光谱特征解耦,有效解决了地面观测中波长校准不稳定的问题。该方法特别适用于大规模巡天数据的快速处理,如ZTF(Zwicky Transient Facility)项目产生的海量光谱数据。RBTL方法在ZTF-SEDm光谱数据集上实现了0.129 mag的离散度控制,相比传统SALT方法提升约24%,显著降低了宿主

weixin_30851867的博客 383

ASP.NET 穿过代理服务器远程用户真实IP地址

 1/**////  2        /// 穿过代理服务器远程用户真实IP地址 3        ///  4        ///  5        private string GetClientIP() 6        { 7            if(Request.ServerVariables["HTTP_VIA"]!=null) 8            { 9   

伟大的饺子 804

ASP.NET中穿过代理服务器远程用户真实IP地址

if(Request.ServerVariables["HTTP_VIA"]!=null){ string user_IP=Request.ServerVariables["HTTP_X_FORWARDED_FOR"].ToString(); }else{ string user_IP=Request.ServerVariables["REMOTE_ADDR"].ToString(); } 应该可

tjgjp的专栏 538

asp dotnet core 从 Frp 获用户真实 IP 地址

我在本地开一个服务,然后通过 Frp 让小伙伴可以在外网访问我的 API 连接,但是直接通过 RemoteIp 拿到的是本地的地址。本文告诉小伙伴如何通过 Frp 可以拿到用户的真实 IP 地址

lindexi 1527

ASP.NET用户端的真实IP

ASP.NET用户端的真实IP在各种场景都能用到,但是用户网端变幻莫测情况众多,获真实IP还真是不容易啊。下面分享个比较好一点的方法: 获IP初始版本 /// <summary> /// 获得当前页面客户端的IP /// Author:codeo.cn /// </summary> //...

weixin_30412013的博客 1318

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

I'm totally new to the ASP.NET MVC stack, and I was wondering what happened to the simple Page obje

w36680130的博客 3145

Asp.Net客户端真实IP方法总结

文章目录#需求场景#HTTP协议头: REMOTE_ADDR,HTTP_CLIENT_IP,HTTP_X_FORWARDED_FOR#简单了解#具体情况分析1、没有使用代理服务器的情况:2、使用透明代理服务器的情况:Transparent Proxies3、使用普通匿名代理服务器的情况:Anonymous Proxies4、使用欺骗性代理服务器的情况:Distorting Proxies5、使用高匿名代理服务器的情况:High Anonymity Proxies (Elite proxies)#Asp.Ne

willingtolove的博客 1950

ASP.NET客户端IP及MAC地址

 获客户端IP:private string GetClientIP()  {   string result = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];   if (null == result || result == String.Empty)   {    result = HttpCo

jxufewbt的专栏 7027

ASP.NET Core 2.x中获客户端IP地址

一、前言 大家也知道服务端请求时我们获IP地址是包含在请求头中,因此这也大大便利了IP的获。 在ASP.NET中,可以通过以下方式获客户端的IP地址。 HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] 但这不适用于ASP.NET Core 2.0。我们需要一种不同的方法来检索HTTP请求信...

kevin860的博客 1754

ASP.NET如何判断IP地址是否在某个IP的范围内实例

ASP.NET如何判断IP地址是否在某个IP的范围内实例

u013334925的博客 845

asp.netCDN用户真实IP的方法,仅供参考!

转文者,请注明本文转自:http://zituo.blog.sohu.com 谢谢。 以下是asp.net代码,一共用到两个方法。 当用户没有使用代理时,能正常出用户的IP地址。用户使用代理时,出的是代理IP。 相对于网上的其他方法,自己认为这个方法较为完善,当然可能您碰到的情况比我这更复杂,也可以在此基础上进行扩展。

[SamForum] 708

ASP.NET用户浏览器IP地址等信息

ASP.NET中有一个很重要的Property叫做HttpRequest.ServerVariables,通过这个Property可以出很多用户浏览器的信息,例如IP地址等等。 例如IP地址信息。 trueIP = Request.ServerVariables["REMOTE_ADDR"]; 到底能出那些信息,和IIS服务器有关,详细可以参考IIS Server V...

weixin_30835923的博客 113

获得真实IP地址及分析 (asp.net C#)

目前网上流行的所谓“真实IP地址”的方法,都有bug,没有考虑到多层透明代理的情况。多数代码类似:string IpAddress = (HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]!=null             && HttpContext.

bentonite的专栏 845

C#获真实IP地址及分析

上篇文章提到的“asp.netIP问题”里的方法,都有bug,没有考虑到多层透明代理的情况。代码:string IpAddress = (HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]!=null            &amp;&amp; HttpContext.Current.Request.Serve...

烟花尽散的博客 1031
上一篇: excel 导入 出现未知错误 xp asp.net
下一篇: 解读vs2003、vs2005、vs2008开发Windows CE环境、默认S pda 智能设备
hyhyct
博客等级 码龄16年 27粉丝 41原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值