Làm cách nào để phát hiện người dùng đang sử dụng localhost bằng PHP?


99

Nói cách khác, làm cách nào tôi có thể biết liệu người sử dụng ứng dụng web của tôi có ở trên máy chủ mà ứng dụng đó đang ở hay không? Nếu tôi nhớ không nhầm thì PHPMyAdmin làm điều gì đó như thế này vì lý do bảo mật.

Câu trả lời:


177

Bạn cũng có thể sử dụng $_SERVER['REMOTE_ADDR']địa chỉ IP của máy khách yêu cầu do máy chủ web cung cấp.

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

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

2
Điều này sẽ làm cho điều này thực sự dễ bị phá hơn là giả mạo IP. Bạn thực sự nên thay đổi nó.
Pekka

3
@ skcin7 có thể là cài đặt máy chủ của bạn. kiểm tra nó.
mauris

4
@Pekka 웃 bạn chỉ có thể gửi ví dụ Host: 127.0.0.1và nó sẽ được điền vào HTTP_HOST, vì vậy nó không phải là phương pháp đáng tin cậy chút nào.
Dejan Marjanović

4
Vâng, đây là một lời khuyên tồi và ở dạng hiện tại và cần được chỉnh sửa - hoặc phản đối.
Pekka

3
Đừng quên IPv6:$whitelist = array('127.0.0.1', '::1');
CrazyMax

26

Như một bổ sung, như một chức năng ...

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

5
Theo phương pháp hay, tôi khuyên bạn nên thêm "else return false;" để hàm luôn trả về giá trị boolean. Hoặc thay vào đó, chỉ cần xóa hoàn toàn "if" và thay vào đó "return in_array ($ _SERVER ['REMOTE_ADDR'], $ whitelist);"
Joe Irby

15

Người dùng hệ điều hành mới hơn (Win 7, 8) cũng có thể thấy cần phải đưa địa chỉ từ xa định dạng IPV6 vào mảng danh sách trắng của họ:

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

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

14

$_SERVER["REMOTE_ADDR"]sẽ cho bạn biết IP của người dùng. Tuy nhiên, nó có thể giả mạo.

Kiểm tra câu hỏi tiền thưởng này để thảo luận rất chi tiết.

Tôi nghĩ những gì bạn nhớ với PHPMyAdmin là một cái gì đó khác biệt: Nhiều Máy chủ MySQL được cấu hình để chúng chỉ có thể được truy cập từ localhost vì lý do bảo mật.


Cần lưu ý rằng một số máy chủ MySQL được cấu hình như vậy bằng cách không liên kết với giao diện công khai. Tương tự, nếu bạn muốn hạn chế một ứng dụng PHP theo cách tương tự, bạn nên cân nhắc việc cung cấp nó thông qua một phiên bản apache chỉ được ràng buộc với một giao diện nội bộ.
Frank Farmer

8

Tôi xin lỗi nhưng tất cả những câu trả lời này có vẻ khủng khiếp đối với tôi. Tôi khuyên bạn nên diễn đạt lại câu hỏi vì theo một nghĩa nào đó, tất cả các máy đều là "localhost".

Câu hỏi nên là; Làm cách nào để chạy các đường dẫn mã khác nhau tùy thuộc vào máy mà nó được thực thi.

Theo tôi, cách dễ nhất là tạo một tệp có tên là DEVMACHINE hoặc bất cứ thứ gì bạn thực sự muốn và sau đó chỉ cần kiểm tra

file_exists ('DEVMACHINE')

Hãy nhớ loại trừ tệp này khi tải lên môi trường lưu trữ trực tiếp!

Giải pháp này không phụ thuộc vào cấu hình mạng, nó không thể bị giả mạo và giúp dễ dàng chuyển đổi giữa chạy "mã trực tiếp" và "mã phát triển".


6

Có vẻ như bạn không nên sử dụng $_SERVER['HTTP_HOST'], vì đây là giá trị trong tiêu đề http, dễ bị làm giả.

Bạn cũng có thể sử dụng $_SERVER["REMOTE_ADDR"], đây là giá trị an toàn hơn, nhưng cũng có thể làm giả. Đây remote_addrlà địa chỉ mà Apache trả về kết quả.


REMOTE_ADDRcó thể làm giả, tuy nhiên nếu bạn muốn làm giả 127.0.0.1hoặc ::1, điều đó đòi hỏi phải làm tổn hại đến máy, mà tại đó, việc giả mạo REMOTE_ADDRlà điều bạn ít lo lắng nhất. Câu trả lời có liên quan - stackoverflow.com/a/5092951/3774582
Goose

1

Nếu bạn muốn có danh sách trắng / danh sách cho phép hỗ trợ IP tĩnhtên động .

Ví dụ:

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

Bằng cách này, bạn có thể thiết lập một danh sách các tên / IP có thể (chắc chắn) được phát hiện. Tên động tăng thêm tính linh hoạt để truy cập từ các điểm khác nhau.

Bạn có hai tùy chọn phổ biến ở đây, bạn có thể đặt tên trong tệp máy chủ cục bộ của mình hoặc bạn có thể chỉ sử dụng một nhà cung cấp tên động có thể tìm thấy ở bất kỳ đâu.

Hàm CACHES này cho kết quả vì gethostbyname là một hàm rất chậm.

Đối với con chó con này, tôi đã triển khai chức năng này:

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;
}

Để có độ tin cậy cao hơn, bạn có thể thay thế $ _SERVER ['REMOTE_ADDR'] cho get_ip_address () mà @Pekka đã đề cập trong bài đăng của mình là "câu hỏi tiền thưởng này"


1
Tôi không biết tại sao ai đó lại đặt điểm tiêu cực cho câu trả lời của tôi trong khi nó rõ ràng cung cấp độ phân giải tên động và những người khác thì không. Độ phân giải DNS chậm, đó là lý do tại sao yêu cầu độ phân giải bộ nhớ đệm.
Heroselohim

1

Làm thế nào để so sánh $_SERVER['SERVER_ADDR'] === $_SERVER['REMOTE_ADDR']để xác định xem máy khách có trên cùng một máy với máy chủ hay không?


$_SERVER['SERVER_ADDR']không phải lúc nào cũng trả về địa chỉ máy chủ một cách đáng tin cậy, ví dụ như nếu sử dụng bộ cân bằng tải, nó sẽ trả về địa chỉ IP của bộ cân bằng tải mà tôi tin tưởng.
Mike W

-2

Tôi đã tìm thấy một câu trả lời dễ dàng.

Bởi vì tất cả các ổ đĩa cục bộ đều có C: hoặc D: hoặc F: ... v.v.

Chỉ cần phát hiện xem ký tự thứ hai có phải là:

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';
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.