客户端 IP 获取指引

更新于:2018年05月04日 16:49:39

一、背景介绍

H5 支付要求商户上传用户真实 IP 地址 client_ip,为保证微信端获取的用户 ip 地址与商户端获取的一致,提供了以下获取用户 ip 的指引,希望对大家有所帮助。

二、没有代理的情况

在商户的前端接入层没有做代理的情况下获取 ip 的方式比较简单,直接获取 'REMOTE_ADDR' 即可:

function get_client_ip()
{
    $cip = "unknown";
    if ($_SERVER['REMOTE_ADDR'])
    {
        $cip = $_SERVER['REMOTE_ADDR'];
    }
    elseif (getenv("REMOTE_ADDR"))
    {
        $cip = getenv("REMOTE_ADDR");
    }
    return $cip
}

三、有代理的情况


在有代理的情况下,因为要代替客户端去访问服务器,所以,当请求包经过反向代理后,在代理服务器这里这个 IP 数据包的 IP 包头做了修改,最终后端 WEB 服务器得到的数据包的头部源 IP 地址是代理服务器的 IP 地址。这样一来,后端服务器的程序就无法获取用户的真实 ip 。

  • nginx 有代理的情况:

在 nginx 中配置中加入

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Real-Port $remote_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  • Apache 有代理的情况:

vi /usr/local/apache/conf/httpd.conf
Include conf/extra/httpd-remoteip.conf
vi /usr/local/apache/conf/extra/httpd-remoteip.conf
LoadModule remoteip_module modules/mod_remoteip.so
RemoteIPHeader X-Forwarded-For
RemoteIPInternalProxy 127.0.0.1
  • 代码 示例

string GetClientIp(CgiInput* poInput) 
{   
    string client_ip = "";   
    string strClientIPList;   
    GetHttpHeader("X-Forwarded-For", strClientIPList);      
    if (strClientIPList.empty())   
    {     
        GetHttpHeader("X-Real-IP", strClientIPList);   
    }      
    if (!strClientIPList.empty())   
    {     
        size_t iPos = strClientIPList.find( "," );     
        if( iPos != std::string::npos )     
        {       
            client_ip = strClientIPList.substr( iPos );     
        }     
        else     
        {       
            client_ip = strClientIPList;     
        }   
    }      
    if (client_ip.empty())   
    {     
        GetHttpHeader("PROXY_FORWARDED_FOR", strClientIPList);     
        // 做下兼容     
        if(strClientIPList.empty())     
        {     
            client_ip = getRemoteAddr();     
        }     
        else     
        {       
            size_t iPos = strClientIPList.find( "," );       
            if( iPos != std::string::npos )       
            {       
                client_ip = strClientIPList.substr( iPos );       
            }       
            else       
            {       
                client_ip = strClientIPList;       
            }      
        }   
    }    
    if(!MMPayCommFunc::IsIp(client_ip))   
    client_ip = getRemoteAddr();   
    return client_ip; 
}


    您需要登录后才可以回复