PHP獲取用戶真實IP的正確姿勢

1.前言

PHP如何獲取用戶的真實IP地址?如果看過一些入門教科書的朋友可能會記得,書上告訴我們使用如下方法獲取:$_SERVER["REMOTE_ADDR"]但是現實真的是如此嗎?並不是,因爲隨着互聯網的發展,我們訪問的途徑變得多種多樣,用戶可以使用代理IP代理訪問、也可能通過CDN加速訪問,那麼你所獲取的IP可能只是代理或者最近一個節點的IP,而不是真實用戶的IP。

2.打印服務器在不同狀態下的捕捉情況

根據下面的代碼,我們可以得到各個CDN加速後的IP結果:

<?php
print_r($_SERVER);
?>

2.1百度CDN打印結果

Array
(
    [HTTP_X_FORWARDED_FOR] => 119.164.27.53,123.234.0.103,27.221.124.94
    [HTTP_X_REAL_IP] => 119.164.27.53
    [REMOTE_ADDR] => 150.138.138.169
    .........

2.2阿里CDN打印結果

Array
(
    [HTTP_ALI_CDN_REAL_IP] => 119.164.27.53
    [HTTP_X_FORWARDED_FOR] => 119.164.27.53
    [REMOTE_ADDR] => 115.124.31.68
    .........
)

2.3七雲牛CDN打印結果

Array
(
    [HTTP_ALI_CDN_REAL_IP] => 119.164.27.53
    [HTTP_X_FORWARDED_FOR] => 119.164.27.53
    [REMOTE_ADDR] => 182.92.246.161
    .........
)

綜上幾家常見的CDN加速,我們可以總結出:使用CDN時,$_SERVER變量中就會含有“HTTP_X_FORWARDED_FOR”元素,並且它裏面含有用戶的真實IP地址,所以根據這個特點,我們可以封裝出以下函數:

function _get_client_ip() {
    $clientip = '';
    if(getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown')) {
        $clientip = getenv('HTTP_CLIENT_IP');
    } elseif(getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown')) {
        $clientip = getenv('HTTP_X_FORWARDED_FOR');
    } elseif(getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), 'unknown')) {
        $clientip = getenv('REMOTE_ADDR');
    } elseif(isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) {
        $clientip = $_SERVER['REMOTE_ADDR'];
    }
    preg_match("/[\d.]{7,15}/", $clientip, $clientipmatches);
    $clientip = $clientipmatches[0] ? $clientipmatches[0] : 'unknown';
    return $clientip;
}

先解釋一下 REMOTE_ADDR 、 HTTP_X_FORWARDED_FOR 、 HTTP_CLIENT_IP 是什麼?不然看的一臉懵逼。

  • REMOTE_ADDR 表示訪客 IP ,如果使用代理訪問則顯示代理 IP
  • HTTP_X_FORWARDED_FOR 表示訪客 IP ,如果不使用代理訪問則爲空
  • HTTP_CLIENT_IP 表示代理服務器 IP ,如果不使用代理訪問則爲空

PS: REMOTE_ADDR 是無法更改的,而 HTTP_X_FORWARDED_FOR 、 HTTP_CLIENT_IP 是由客戶端(一般指代理服務器)自行設定的。

3.根據不同需求選擇不同方案

對於IP地址的獲取和使用,我們應該根據業務和需求獲取用戶的IP地址。

3.1投票系統/活動

做投票系統/活動的時候最主要的是防止刷票,所以推薦使用使用$_SERVER["REMOTE_ADDR"]去獲取客戶 IP ,因爲通過HTTP_X_FORWARDED_FOR 、 HTTP_CLIENT_IP 獲取到的IP有可能是刷票者僞造的,而$_SERVER["REMOTE_ADDR"]是最穩妥的

3.2網站訪問統計

此時應該使用我們封裝的函數去獲取用戶的IP地址,以便訪客通過代理服務器訪問網站時能獲取到訪客的真實 IP,如果你認爲網絡比較複雜,你可以同時存儲REMOTE_ADDRHTTP_X_FORWARDED_FORHTTP_CLIENT_IP

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章