ฉันจะตรวจสอบได้อย่างไรว่าผู้ใช้อยู่ใน localhost ใน PHP?


100

กล่าวอีกนัยหนึ่งฉันจะทราบได้อย่างไรว่าบุคคลที่ใช้เว็บแอปพลิเคชันของฉันอยู่บนเซิร์ฟเวอร์ที่อาศัยอยู่ ถ้าจำไม่ผิด PHPMyAdmin ทำอะไรแบบนี้ด้วยเหตุผลด้านความปลอดภัย

คำตอบ:


179

คุณยังสามารถใช้$_SERVER['REMOTE_ADDR']สำหรับที่อยู่ IP ของไคลเอนต์ที่ร้องขอโดยเว็บเซิร์ฟเวอร์

$whitelist = array(
    '127.0.0.1',
    '::1'
);

if(!in_array($_SERVER['REMOTE_ADDR'], $whitelist)){
    // not valid
}

2
ซึ่งจะทำให้สามารถทำลายได้ง่ายกว่าการปลอมแปลง IP คุณควรเปลี่ยนมันจริงๆ
Pekka

3
@ skcin7 อาจเป็นการตั้งค่าเซิร์ฟเวอร์ของคุณ ตรวจสอบ.
mauris

4
@Pekka 웃คุณสามารถส่งเช่นHost: 127.0.0.1และมันจะถูกเติมเข้าไปHTTP_HOSTดังนั้นจึงไม่ใช่วิธีที่เชื่อถือได้เลย
Dejan Marjanović

4
ใช่นี่เป็นคำแนะนำที่ไม่ดีและอยู่ในรูปแบบปัจจุบันและจำเป็นต้องแก้ไขหรือลดระดับลง
Pekka

3
อย่าลืม IPv6:$whitelist = array('127.0.0.1', '::1');
CrazyMax

26

เป็นส่วนเติมเต็มตามหน้าที่ ...

function isLocalhost($whitelist = ['127.0.0.1', '::1']) {
    return in_array($_SERVER['REMOTE_ADDR'], $whitelist);
}

5
ตามแนวทางปฏิบัติที่ดีฉันขอแนะนำให้เพิ่ม "else return false;" เพื่อให้ฟังก์ชันส่งคืนค่าบูลีนเสมอ หรืออีกวิธีหนึ่งก็คือลบ "if" ทั้งหมดและแทนที่ "return in_array ($ _SERVER ['REMOTE_ADDR'], $ whitelist);"
Joe Irby

16

ผู้ใช้ระบบปฏิบัติการรุ่นใหม่ (Win 7, 8) อาจพบว่าจำเป็นต้องรวมที่อยู่ระยะไกลรูปแบบ IPV6 ไว้ในอาร์เรย์รายการที่อนุญาต:

$whitelist = array('127.0.0.1', "::1");

if(!in_array($_SERVER['REMOTE_ADDR'], $whitelist)){
    // not valid
}

14

$_SERVER["REMOTE_ADDR"]ควรบอก IP ของผู้ใช้ แม้ว่ามันจะหลอกลวง

ตรวจสอบคำถามที่มีค่าตอบแทนนี้เพื่อการสนทนาโดยละเอียด

ฉันคิดว่าสิ่งที่คุณจำได้กับ PHPMyAdmin นั้นแตกต่างออกไป: เซิร์ฟเวอร์ MySQL จำนวนมากได้รับการกำหนดค่าเพื่อให้สามารถเข้าถึงได้จาก localhost เท่านั้นเพื่อความปลอดภัย


เป็นที่น่าสังเกตว่าเซิร์ฟเวอร์ MySQL บางตัวได้รับการกำหนดค่าโดยไม่ผูกมัดกับอินเทอร์เฟซสาธารณะ ในทำนองเดียวกันหากคุณต้องการ จำกัด แอปพลิเคชัน PHP ในลักษณะเดียวกันคุณควรพิจารณาให้บริการผ่านอินสแตนซ์ apache ที่ผูกไว้กับอินเทอร์เฟซภายในเท่านั้น
Frank Farmer

7

ฉันขอโทษ แต่คำตอบทั้งหมดนี้ดูเหมือนแย่มากสำหรับฉัน ฉันขอแนะนำให้เปลี่ยนวลีคำถามเพราะในแง่หนึ่งเครื่องทั้งหมดเป็น "localhost"

คำถามควรจะ; ฉันจะเรียกใช้เส้นทางรหัสที่แตกต่างกันได้อย่างไรโดยขึ้นอยู่กับเครื่องที่ใช้งาน

ในความคิดของฉันวิธีที่ง่ายที่สุดคือสร้างไฟล์ชื่อ DEVMACHINE หรืออะไรก็ได้ที่คุณต้องการจริงๆแล้วตรวจสอบ

file_exists ('DEVMACHINE')

อย่าลืมยกเว้นไฟล์นี้เมื่ออัปโหลดไปยังสภาพแวดล้อมการโฮสต์สด!

โซลูชันนี้ไม่ได้ขึ้นอยู่กับการกำหนดค่าเครือข่ายจึงไม่สามารถปลอมแปลงได้และทำให้ง่ายต่อการสลับระหว่างการเรียกใช้ "live-code" และ "dev-code"


6

ดูเหมือนว่าคุณไม่ควรใช้$_SERVER['HTTP_HOST']เพราะนี่คือค่าในส่วนหัว http ซึ่งปลอมแปลงได้ง่าย

คุณอาจใช้$_SERVER["REMOTE_ADDR"]มากเกินไปนี่เป็นค่าที่ปลอดภัยกว่า แต่ก็เป็นไปได้ที่จะปลอม นี่remote_addrคือที่อยู่ที่ Apache ส่งคืนผลลัพธ์


REMOTE_ADDRเป็นไปได้ที่จะปลอมอย่างไรก็ตามหากคุณต้องการปลอมเป็น127.0.0.1หรือ ::1ต้องมีการประนีประนอมกับเครื่องจักรซึ่งการปลอมแปลงREMOTE_ADDRเป็นสิ่งที่คุณกังวลน้อยที่สุด คำตอบที่เกี่ยวข้อง - stackoverflow.com/a/5092951/3774582
Goose

1

หากคุณต้องการที่จะมีรายการที่อนุญาต / allowlistที่สนับสนุนIP ที่คงที่และชื่อแบบไดนามิก

ตัวอย่างเช่น:

$whitelist = array("localhost", "127.0.0.1", "devel-pc.ds.com", "liveserver.com");
if (!isIPWhitelisted($whitelist)) die();

ด้วยวิธีนี้คุณสามารถกำหนดรายชื่อ / IPที่จะสามารถตรวจพบได้ (แน่นอน) ชื่อแบบไดนามิกช่วยเพิ่มความยืดหยุ่นในการเข้าถึงจากจุดต่างๆ

คุณมีสองตัวเลือกทั่วไปที่นี่คุณสามารถตั้งชื่อในไฟล์โฮสต์ในเครื่องของคุณหรือคุณสามารถใช้ผู้ให้บริการชื่อไดนามิกเพียงรายเดียวที่สามารถพบได้ทุกที่

ฟังก์ชันนี้ CACHES ผลลัพธ์เนื่องจาก gethostbyname เป็นฟังก์ชันที่ช้ามาก

สำหรับ pupose นี้ฉันได้ใช้ฟังก์ชันนี้:

function isIPWhitelisted($whitelist = false)
{
    if ( isset($_SESSION) && isset($_SESSION['isipallowed']) )
        { return $_SESSION['isipallowed'];  }

    // This is the whitelist
    $ipchecklist = array("localhost", "127.0.0.1", "::1");
    if ($whitelist) $ipchecklist = $whitelist;

    $iplist = false;
    $isipallowed = false;

    $filename = "resolved-ip-list.txt";
    $filename = substr(md5($filename), 0, 8)."_".$filename; // Just a spoon of security or just remove this line

    if (file_exists($filename))
    {
        // If cache file has less than 1 day old use it
        if (time() - filemtime($filename) <= 60*60*24*1)
            $iplist = explode(";", file_get_contents($filename)); // Read cached resolved ips
    }

    // If file was not loaded or found -> generate ip list
    if (!$iplist)
    {
        $iplist = array(); $c=0;
        foreach ( $ipchecklist as $k => $iptoresolve )
        {
            // gethostbyname: It's a VERY SLOW function. We really need to cache the resolved ip list
            $ip = gethostbyname($iptoresolve);
            if ($ip != "") $iplist[$c] = $ip;
            $c++;
        }

        file_put_contents($filename, implode(";", $iplist));
    }

    if (in_array($_SERVER['REMOTE_ADDR'], $iplist)) // Check if the client ip is allowed
        $isipallowed = true;

    if (isset($_SESSION)) $_SESSION['isipallowed'] = $isipallowed;

    return $isipallowed;
}

เพื่อความน่าเชื่อถือที่ดีขึ้นคุณสามารถแทนที่$ _SERVER ['REMOTE_ADDR']สำหรับget_ip_address ()ที่ @Pekka กล่าวถึงในโพสต์ของเขาว่า"คำถามนี้มีค่า"


1
ฉันไม่รู้ว่าทำไมใครบางคนถึงให้คะแนนติดลบกับคำตอบของฉันในขณะที่มันเสนอการแก้ชื่อแบบไดนามิกอย่างชัดเจนและอื่น ๆ ไม่ การแก้ปัญหา DNS ช้านั่นเป็นสาเหตุที่ต้องใช้ความละเอียดในการแคช
Heroselohim

1

จะเปรียบเทียบ$_SERVER['SERVER_ADDR'] === $_SERVER['REMOTE_ADDR']เพื่อตรวจสอบว่าไคลเอนต์อยู่บนเครื่องเดียวกันกับเซิร์ฟเวอร์ได้อย่างไร?


$_SERVER['SERVER_ADDR']ไม่ได้ส่งคืนที่อยู่เซิร์ฟเวอร์อย่างน่าเชื่อถือเสมอไปเช่นหากใช้ตัวโหลดบาลานเซอร์มันจะส่งคืนที่อยู่ IP ของตัวโหลดบาลานเซอร์ที่ฉันเชื่อ
Mike W

-5

ฉันพบคำตอบง่ายๆ

เนื่องจากไดรฟ์ภายในเครื่องทั้งหมดมี C: หรือ D: หรือ F: ... เป็นต้น

เพียงตรวจสอบว่าอักขระที่สองเป็น:

if ( substr_compare(getcwd(),":",1,1) == 0)
{
echo '<script type="text/javascript">alert(" The working dir is at the local computer ")</script>';
    $client_or_server = 'client';
}
else
{
echo '<script type="text/javascript">alert(" The working dir is at the server ")</script>';
    $client_or_server = 'server';
}

วิธีนี้ดูเหมือนจะค่อนข้างอ่อนไหวต่อข้อผิดพลาดและใช้ได้กับ Windows เท่านั้น
Husky
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.