a

Câu hỏi Cách chính xác nhất để lấy địa chỉ IP chính xác của người dùng trong PHP là gì?


Tôi biết có rất nhiều $ _SERVER các tiêu đề biến có sẵn để truy xuất địa chỉ IP. Tôi đã tự hỏi nếu có một sự đồng thuận chung như thế nào để chính xác nhất lấy địa chỉ IP thực sự của người dùng (cũng biết không có phương pháp là hoàn hảo) bằng cách sử dụng các biến nói?

Tôi đã dành thời gian cố gắng tìm một giải pháp chuyên sâu và đã đưa ra đoạn mã sau dựa trên một số nguồn. Tôi rất thích nó nếu ai đó có thể xin vui lòng chọc lỗ trong câu trả lời hoặc làm sáng tỏ một số thứ có lẽ chính xác hơn.

chỉnh sửa bao gồm tối ưu hóa từ @Alix

 /**
  * Retrieves the best guess of the client's actual IP address.
  * Takes into account numerous HTTP proxy headers due to variations
  * in how different ISPs handle IP addresses in headers between hops.
  */
 public function get_ip_address() {
  // Check for shared internet/ISP IP
  if (!empty($_SERVER['HTTP_CLIENT_IP']) && $this->validate_ip($_SERVER['HTTP_CLIENT_IP']))
   return $_SERVER['HTTP_CLIENT_IP'];

  // Check for IPs passing through proxies
  if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
   // Check if multiple IP addresses exist in var
    $iplist = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
    foreach ($iplist as $ip) {
     if ($this->validate_ip($ip))
      return $ip;
    }
   }
  }
  if (!empty($_SERVER['HTTP_X_FORWARDED']) && $this->validate_ip($_SERVER['HTTP_X_FORWARDED']))
   return $_SERVER['HTTP_X_FORWARDED'];
  if (!empty($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']) && $this->validate_ip($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']))
   return $_SERVER['HTTP_X_CLUSTER_CLIENT_IP'];
  if (!empty($_SERVER['HTTP_FORWARDED_FOR']) && $this->validate_ip($_SERVER['HTTP_FORWARDED_FOR']))
   return $_SERVER['HTTP_FORWARDED_FOR'];
  if (!empty($_SERVER['HTTP_FORWARDED']) && $this->validate_ip($_SERVER['HTTP_FORWARDED']))
   return $_SERVER['HTTP_FORWARDED'];

  // Return unreliable IP address since all else failed
  return $_SERVER['REMOTE_ADDR'];
 }

 /**
  * Ensures an IP address is both a valid IP address and does not fall within
  * a private network range.
  *
  * @access public
  * @param string $ip
  */
 public function validate_ip($ip) {
     if (filter_var($ip, FILTER_VALIDATE_IP, 
                         FILTER_FLAG_IPV4 | 
                         FILTER_FLAG_IPV6 |
                         FILTER_FLAG_NO_PRIV_RANGE | 
                         FILTER_FLAG_NO_RES_RANGE) === false)
         return false;
     self::$ip = $ip;
     return true;
 }

Lời cảnh báo (cập nhật)

REMOTE_ADDR vẫn đại diện cho đáng tin cậy nhất nguồn của địa chỉ IP. Cai khac $_SERVER các biến được đề cập ở đây có thể được giả mạo bởi một ứng dụng khách từ xa rất dễ dàng. Mục đích của giải pháp này là cố gắng xác định địa chỉ IP của một khách hàng đang ngồi sau một proxy. Vì mục đích chung của bạn, bạn có thể xem xét việc sử dụng kết hợp này với địa chỉ IP được trả về trực tiếp từ $_SERVER['REMOTE_ADDR'] và lưu trữ cả hai.

Đối với 99,9% người dùng, giải pháp này sẽ phù hợp với nhu cầu của bạn một cách hoàn hảo. Nó sẽ không bảo vệ bạn khỏi 0,1% người dùng độc hại tìm cách lạm dụng hệ thống của bạn bằng cách tiêm các tiêu đề yêu cầu của riêng họ. Nếu dựa vào địa chỉ IP cho một nhiệm vụ quan trọng, hãy REMOTE_ADDR và đừng bận tâm đến những người đứng sau một proxy.


259
2017-10-28 02:03


gốc


Đối với câu hỏi whatismyip.com, tôi nghĩ rằng họ làm điều gì đó giống như tập lệnh này, bạn có đang chạy nó cục bộ không? Nếu bạn là thats lý do tại sao bạn có một IP nội bộ, không có gì là nhận được gửi qua giao diện công cộng trong trường hợp đó vì vậy không có thông tin cho php để có được - Matt
Đảm bảo bạn ghi nhớ điều này khi thực hiện điều này: stackoverflow.com/questions/1672827/… - Kevin Peno
Hãy nhớ rằng tất cả các tiêu đề HTTP này thực sự dễ sửa đổi: với giải pháp của bạn, tôi chỉ cần định cấu hình trình duyệt của mình để gửi tiêu đề X-Forwarded-For với IP ngẫu nhiên và tập lệnh của bạn sẽ trả về địa chỉ giả một cách vui vẻ. Vì vậy, tùy thuộc vào những gì bạn đang cố gắng làm, giải pháp này có thể kém đáng tin cậy hơn là chỉ sử dụng REMOTE_ADDR. - gnomnain
OMFG, "ip không đáng tin cậy"! Lần đầu tiên tôi thấy một điều vô lý ở đây trên SO. Địa chỉ IP đáng tin cậy duy nhất là REMOTE_ADDR - Your Common Sense
-1 điều này dễ bị lừa đảo. Tất cả những gì bạn đang làm là hỏi người dùng địa chỉ ip của mình. - rook


Các câu trả lời:


Đây là cách ngắn gọn hơn, gọn gàng hơn để lấy địa chỉ IP:

function get_ip_address(){
    foreach (array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR') as $key){
        if (array_key_exists($key, $_SERVER) === true){
            foreach (explode(',', $_SERVER[$key]) as $ip){
                $ip = trim($ip); // just to be safe

                if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false){
                    return $ip;
                }
            }
        }
    }
}

Tôi hy vọng nó sẽ giúp!


Mã của bạn có vẻ khá hoàn chỉnh rồi, tôi không thể nhìn thấy bất kỳ lỗi nào có thể xảy ra trong đó (ngoài những cảnh báo IP thông thường), tôi sẽ thay đổi validate_ip() chức năng dựa vào phần mở rộng của bộ lọc mặc dù:

public function validate_ip($ip)
{
    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) === false)
    {
        return false;
    }

    self::$ip = sprintf('%u', ip2long($ip)); // you seem to want this

    return true;
}

Cũng của bạn HTTP_X_FORWARDED_FOR đoạn mã có thể được đơn giản hóa từ điều này:

// check for IPs passing through proxies
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
{
    // check if multiple ips exist in var
    if (strpos($_SERVER['HTTP_X_FORWARDED_FOR'], ',') !== false)
    {
        $iplist = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);

        foreach ($iplist as $ip)
        {
            if ($this->validate_ip($ip))
                return $ip;
        }
    }

    else
    {
        if ($this->validate_ip($_SERVER['HTTP_X_FORWARDED_FOR']))
            return $_SERVER['HTTP_X_FORWARDED_FOR'];
    }
}

Để điều này:

// check for IPs passing through proxies
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
{
    $iplist = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);

    foreach ($iplist as $ip)
    {
        if ($this->validate_ip($ip))
            return $ip;
    }
}

Bạn cũng có thể muốn xác thực địa chỉ IPv6.


212
2018-01-09 01:23



Tôi chắc chắn đánh giá cao filter_var sửa chữa vì nó loại bỏ một loạt các kiểm tra int không được kiểm tra int trên địa chỉ IP. Tôi cũng thích thực tế nó mang lại cho tôi tùy chọn xác thực địa chỉ IPv6. Các HTTP_X_FORWARDED_FOR tối ưu hóa cũng được nhiều đánh giá cao. Trong một vài phút, tôi sẽ cập nhật mã. - Corey Ballou
-1 đây là dễ bị giả mạo tất cả các bạn đang làm là yêu cầu người sử dụng những gì địa chỉ ip của mình nên được. - rook
@Rook: Vâng, tôi biết. OP là nhận thức được điều đó, và tôi cũng đã đề cập đến nó trong câu trả lời của tôi. Nhưng cảm ơn cho bình luận. - Alix Axel
FYI: Tôi phải xóa FILTER_FLAG_IPV6 để mã của Alix Axel hoạt động. - darkAsPitch
@ rubenrp81 Trình xử lý socket TCP là nguồn kinh điển duy nhất, mọi thứ khác đều được kiểm soát bởi kẻ tấn công. Đoạn mã trên là giấc mơ của kẻ tấn công. - rook


Tuy nhiên, ngay cả khi nhận được địa chỉ IP thực sự của người dùng sẽ không đáng tin cậy. Tất cả những gì họ cần làm là sử dụng một máy chủ proxy ẩn danh (một máy chủ không tôn trọng tiêu đề cho http_x_forwarded_for, http_forwarded, vv) và tất cả những gì bạn nhận được là địa chỉ IP của máy chủ proxy của họ.

Sau đó bạn có thể xem nếu có một danh sách các địa chỉ IP của máy chủ proxy ẩn danh, nhưng không có cách nào để chắc chắn rằng chính xác 100% là tốt nhất và điều tốt nhất nó làm là cho bạn biết đó là máy chủ proxy. Và nếu ai đó thông minh, họ có thể giả mạo tiêu đề cho HTTP chuyển tiếp.

Giả sử tôi không thích trường đại học địa phương. Tôi tìm ra địa chỉ IP nào họ đã đăng ký và nhận địa chỉ IP của họ bị cấm trên trang web của bạn bằng cách làm những điều xấu, vì tôi tìm ra bạn tôn trọng HTTP chuyển tiếp. Danh sách là vô tận.

Sau đó, như bạn đã đoán, các địa chỉ IP nội bộ như mạng lưới trường đại học mà tôi đã đạt được trước đó. Rất nhiều sử dụng một định dạng 10.x.x.x. Vì vậy, tất cả các bạn sẽ biết là nó đã được chuyển tiếp cho một mạng chia sẻ.

Sau đó, tôi sẽ không bắt đầu nhiều vào nó, nhưng địa chỉ IP động là con đường của băng thông rộng nữa. Vì thế. Ngay cả khi bạn nhận được địa chỉ IP của người dùng, hy vọng nó sẽ thay đổi trong 2 - 3 tháng, dài nhất.


9
2017-10-28 07:37



Cảm ơn các đầu vào. Tôi hiện đang sử dụng địa chỉ IP của người dùng để hỗ trợ xác thực phiên bằng cách sử dụng IP lớp C của họ như một yếu tố hạn chế để hạn chế tấn công phiên nhưng cho phép IP động trong phạm vi lý do. IP giả mạo và máy chủ proxy ẩn danh chỉ là thứ tôi sẽ phải đối phó với một nhóm người được chọn. - Corey Ballou
Cool :) Tôi rất vui vì tôi có thể giúp :)
@cballou - Chắc chắn cho mục đích này REMOTE_ADDR là một trong những chính xác để sử dụng. Bất kỳ phương pháp nào dựa vào tiêu đề HTTP đều dễ bị giả mạo tiêu đề. Một phiên là bao lâu? IP động không thay đổi nhanh. - MZB
Họ làm, đặc biệt là nếu tôi muốn họ (thay đổi địa chỉ mac mà nhiều trình điều khiển hỗ trợ). Chỉ cần REMOTE_ADDR là đủ để có được máy chủ cuối cùng mà nó đã nói đến là gì. Vì vậy, trong một tình huống proxy bạn nhận được IP proxy.


Chúng tôi sử dụng:

/**
 * Get the customer's IP address.
 *
 * @return string
 */
public function getIpAddress() {
    if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
        return $_SERVER['HTTP_CLIENT_IP'];
    } else if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
        return trim($ips[count($ips) - 1]);
    } else {
        return $_SERVER['REMOTE_ADDR'];
    }
}

Sự bùng nổ trên HTTP_X_FORWARDED_FOR là do các vấn đề lạ mà chúng tôi đã phát hiện địa chỉ IP khi Mực ống đã được dùng.


5
2018-01-07 20:41



Rất tiếc, tôi vừa mới nhận ra bạn về cơ bản cũng giống như vậy với việc bùng nổ, v.v. Cộng thêm một chút. Vì vậy, tôi nghi ngờ câu trả lời của tôi đã giúp đỡ rất nhiều. :) - gabrielk
Điều này trả về địa chỉ của localhost - Scarl


Câu hỏi lớn nhất là vì mục đích gì?

Mã của bạn gần như toàn diện như nó có thể - nhưng tôi thấy rằng nếu bạn phát hiện ra cái gì giống như một header được thêm vào proxy, bạn dùng INSTEAD của CLIENT_IP, tuy nhiên nếu bạn muốn thông tin này cho mục đích kiểm tra thì được cảnh báo - nó rất dễ giả mạo.

Chắc chắn bạn không bao giờ nên sử dụng địa chỉ IP cho bất kỳ loại xác thực nào - thậm chí chúng có thể bị giả mạo.

Bạn có thể đo lường địa chỉ ip của khách hàng tốt hơn bằng cách đẩy flash hoặc applet java kết nối trở lại máy chủ qua cổng không http (do đó sẽ tiết lộ proxy trong suốt hoặc trường hợp tiêu đề được tiêm proxy sai - nhưng lưu ý rằng, nơi client chỉ có thể kết nối thông qua proxy web hoặc cổng gửi đi bị chặn, sẽ không có kết nối nào từ applet.

C.


2
2018-01-09 14:13



Cân nhắc tôi đang tìm giải pháp duy nhất của PHP, bạn có gợi ý tôi thêm $_SERVER['CLIENT_IP'] như người thứ hai nếu tuyên bố? - Corey Ballou
Không - chỉ cần rằng nếu bạn muốn đặt bất kỳ ý nghĩa nào trên dữ liệu được trả về, thì tốt nhất là bảo vệ địa chỉ điểm cuối của mạng (IP của khách hàng) cũng như bất cứ điều gì đề xuất một giá trị khác nhau trong các tiêu đề được thêm vào proxy (ví dụ: bạn có thể thấy rất nhiều địa chỉ 192.168.1.x nhưng đến từ các máy khách khác nhau) - symcbean


Chỉ là một VB.NET phiên bản của câu trả lời:

Private Function GetRequestIpAddress() As IPAddress
    Dim serverVariables = HttpContext.Current.Request.ServerVariables
    Dim headersKeysToCheck = {"HTTP_CLIENT_IP", _
                              "HTTP_X_FORWARDED_FOR", _
                              "HTTP_X_FORWARDED", _
                              "HTTP_X_CLUSTER_CLIENT_IP", _
                              "HTTP_FORWARDED_FOR", _
                              "HTTP_FORWARDED", _
                              "REMOTE_ADDR"}
    For Each thisHeaderKey In headersKeysToCheck
        Dim thisValue = serverVariables.Item(thisHeaderKey)
        If thisValue IsNot Nothing Then
            Dim validAddress As IPAddress = Nothing
            If IPAddress.TryParse(thisValue, validAddress) Then
                Return validAddress
            End If
        End If
    Next
    Return Nothing
End Function

1
2017-07-09 21:50



Có thẻ "PHP" trong câu hỏi - luchaninov


tôi nhận ra có nhiều câu trả lời tốt hơn và ngắn gọn hơn ở trên, và đây không phải là một chức năng cũng không phải là kịch bản duyên dáng nhất xung quanh. Trong trường hợp của chúng ta, chúng ta cần tạo ra cả x_forwarded_for giả mạo và remote_addr đáng tin cậy hơn trong một chuyển đổi đơn giản cho mỗi câu nói. Nó cần thiết để cho phép khoảng trống để tiêm vào các hàm khác nếu không hoặc không có số ít (thay vì chỉ trả về hàm được định dạng trước). Nó cần một var "on or off" với một nhãn tùy chỉnh cho mỗi switch cho các thiết lập nền tảng. Nó cũng cần một cách để $ ip được năng động tùy theo yêu cầu để nó có dạng forwarded_for.

Ngoài ra tôi đã không thấy bất kỳ địa chỉ isset () vs! Empty () - có thể nhập không có gì cho x_forwarded_for nhưng vẫn kích hoạt isset () true dẫn đến var trống, một cách để có được xung quanh là sử dụng && và kết hợp cả hai điều kiện. Hãy nhớ rằng bạn có thể giả mạo các từ như "PWNED" như x_forwarded_for vì vậy hãy chắc chắn rằng bạn đã khử trùng một cú pháp ip thực nếu xuất hiện ở đâu đó được bảo vệ hoặc vào DB.

Ngoài ra, bạn có thể thử nghiệm bằng cách sử dụng google dịch nếu bạn cần một proxy đa để xem mảng trong x_forwarder_for. Nếu bạn muốn tiêu đề giả mạo để kiểm tra, hãy kiểm tra điều này Tiêu đề khách hàng Chrome Spoof sự mở rộng. Điều này sẽ mặc định chỉ là remote_addr tiêu chuẩn trong khi phía sau proxy anon.

Tôi không biết bất kỳ trường hợp nào mà remote_addr có thể trống, nhưng nó có thể là dự phòng trong trường hợp.

// proxybuster - attempts to un-hide originating IP if [reverse]proxy provides methods to do so
  $enableProxyBust = true;

if (($enableProxyBust == true) && (isset($_SERVER['REMOTE_ADDR'])) && (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) && (!empty($_SERVER['HTTP_X_FORWARDED_FOR']))) {
    $ip = end(array_values(array_filter(explode(',',$_SERVER['HTTP_X_FORWARDED_FOR']))));
    $ipProxy = $_SERVER['REMOTE_ADDR'];
    $ipProxy_label = ' behind proxy ';
} elseif (($enableProxyBust == true) && (isset($_SERVER['REMOTE_ADDR']))) {
    $ip = $_SERVER['REMOTE_ADDR'];
    $ipProxy = '';
    $ipProxy_label = ' no proxy ';
} elseif (($enableProxyBust == false) && (isset($_SERVER['REMOTE_ADDR']))) {
    $ip = $_SERVER['REMOTE_ADDR'];
    $ipProxy = '';
    $ipProxy_label = '';
} else {
    $ip = '';
    $ipProxy = '';
    $ipProxy_label = '';
}

Để làm cho các động này sử dụng trong hàm hoặc truy vấn / echo / xem bên dưới, hãy nói về nhật ký hoặc báo cáo lỗi, sử dụng hình cầu hoặc chỉ lặp lại em ở bất cứ nơi nào bạn muốn mà không tạo ra nhiều điều kiện khác hoặc sơ đồ-đầu ra tĩnh chức năng.

function fooNow() {
    global $ip, $ipProxy, $ipProxy_label;
    // begin this actions such as log, error, query, or report
}

Cảm ơn tất cả những suy nghĩ tuyệt vời của bạn. Xin vui lòng cho tôi biết nếu điều này có thể được tốt hơn, vẫn kinda mới cho các tiêu đề :)


1
2017-08-06 19:07





Tôi đã đưa ra chức năng này mà không đơn giản trả lại địa chỉ IP mà là một mảng với thông tin IP.

// Example usage:
$info = ip_info();
if ( $info->proxy ) {
    echo 'Your IP is ' . $info->ip;
} else {
    echo 'Your IP is ' . $info->ip . ' and your proxy is ' . $info->proxy_ip;
}

Đây là hàm:

/**
 * Retrieves the best guess of the client's actual IP address.
 * Takes into account numerous HTTP proxy headers due to variations
 * in how different ISPs handle IP addresses in headers between hops.
 *
 * @since 1.1.3
 *
 * @return object {
 *         IP Address details
 *
 *         string $ip The users IP address (might be spoofed, if $proxy is true)
 *         bool $proxy True, if a proxy was detected
 *         string $proxy_id The proxy-server IP address
 * }
 */
function ip_info() {
    $result = (object) array(
        'ip' => $_SERVER['REMOTE_ADDR'],
        'proxy' => false,
        'proxy_ip' => '',
    );

    /*
     * This code tries to bypass a proxy and get the actual IP address of
     * the visitor behind the proxy.
     * Warning: These values might be spoofed!
     */
    $ip_fields = array(
        'HTTP_CLIENT_IP',
        'HTTP_X_FORWARDED_FOR',
        'HTTP_X_FORWARDED',
        'HTTP_X_CLUSTER_CLIENT_IP',
        'HTTP_FORWARDED_FOR',
        'HTTP_FORWARDED',
        'REMOTE_ADDR',
    );
    foreach ( $ip_fields as $key ) {
        if ( array_key_exists( $key, $_SERVER ) === true ) {
            foreach ( explode( ',', $_SERVER[$key] ) as $ip ) {
                $ip = trim( $ip );

                if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ) !== false ) {
                    $forwarded = $ip;
                    break 2;
                }
            }
        }
    }

    // If we found a different IP address then REMOTE_ADDR then it's a proxy!
    if ( $forwarded != $result->ip ) {
        $result->proxy = true;
        $result->proxy_ip = $result->ip;
        $result->ip = $forwarded;
    }

    return $result;
}

1
2018-02-04 17:57





Câu trả lời của tôi về cơ bản chỉ là một câu trả lời được đánh giá, được kiểm chứng đầy đủ và được đóng gói đầy đủ, của câu trả lời của @ AlixAxel:

<?php

/* Get the 'best known' client IP. */

if (!function_exists('getClientIP'))
    {
        function getClientIP()
            {
                if (isset($_SERVER["HTTP_CF_CONNECTING_IP"])) 
                    {
                        $_SERVER['REMOTE_ADDR'] = $_SERVER["HTTP_CF_CONNECTING_IP"];
                    };

                foreach (array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR') as $key)
                    {
                        if (array_key_exists($key, $_SERVER)) 
                            {
                                foreach (explode(',', $_SERVER[$key]) as $ip)
                                    {
                                        $ip = trim($ip);

                                        if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false)
                                            {
                                                return $ip;
                                            };
                                    };
                            };
                    };

                return false;
            };
    };

$best_known_ip = getClientIP();

if(!empty($best_known_ip))
    {
        $ip = $clients_ip = $client_ip = $client_IP = $best_known_ip;
    }
else
    {
        $ip = $clients_ip = $client_ip = $client_IP = $best_known_ip = '';
    };

?>

Thay đổi:

  • Nó đơn giản hóa tên hàm (với kiểu định dạng 'camelCase').

  • Nó bao gồm một kiểm tra để đảm bảo chức năng chưa được khai báo trong một phần khác của mã của bạn.

  • Nó có tính đến khả năng tương thích 'CloudFlare'.

  • Nó khởi tạo nhiều tên biến "liên quan đến IP" với giá trị trả về, của hàm 'getClientIP'.

  • Nó đảm bảo rằng nếu hàm không trả về một địa chỉ IP hợp lệ, tất cả các biến được đặt thành một chuỗi rỗng, thay vì null.

  • Chỉ có (45) dòng mã.


1
2017-12-07 14:12



Nhìn rất tốt! - CM 웃