2011-08-09 18 views
9

मुझे यह जांचने की ज़रूरत है कि फ़ाइल "स्थानीय रूप से" (उसी मशीन या नेटवर्क) खोला गया है या नहीं। मैं उपयोग कर रहा हूँ:PHP: क्लाइंट स्थानीय है या नहीं, यह जांचने के लिए कैसे करें?

<?php 
if ((substr($_SERVER['REMOTE_ADDR'],0,8) == "192.168.") || ($_SERVER['REMOTE_ADDR'] == "127.0.0.1")) { 
    // client is local 
} else { 
    // client is not local 
} 

लेकिन मुझे यकीन है यह सबसे अच्छा तरीका है नहीं कर रहा हूँ।

ऐसा करने का एक और मूर्ख तरीका क्या है?

+2

यहां आप आईपीवी 4 पर स्वयं को प्रतिबंधित कर रहे हैं। आजकल, यह पर्याप्त नहीं है। आपको ए) आईपीवी 6 के साथ-साथ बी) परिभाषाओं की एक सूची परिभाषित करें जो 'स्थानीय' है: वास्तव में केवल 1 9 2.168। *? क्या होगा यदि आप अपने आईपी के साथ नेटवर्क में हैं? या एक 10. * नेटवर्क के भीतर? – glglgl

+0

संभावित डुप्लिकेट [कैसे पता चलेगा कि कोई आईपी बाहरी है या नहीं?] (Http://stackoverflow.com/questions/14125735/how-to-now-if-an-ip-is-external-or-not) – user956584

उत्तर

9

"मूर्खतापूर्ण," हमेशा के रूप में, मुश्किल हो सकता है।

अगर हम खुद को आईपीवी 4 तक सीमित करते हैं, तो "127.0.0.1" की जांच स्थानीयहोस्ट मामले की देखभाल करती है, लेकिन "1 9 2.168" के खिलाफ जांच कर रही है। सादा गलत है - यह केवल तभी काम करेगा जब स्क्रिप्ट एक सर्वर पर चल रहा है जो 16-बिट सबनेट मास्क का उपयोग करके 1 9 2.168 नेटवर्क पर होता है।

$ _SERVER ['SERVEMADDR'] के विरुद्ध $ _SERVER ['REMOTE_ADDR'] की जांच करना बेहतर शर्त होगी। यह अभी भी एक बहु-गृह होस्ट (यानी एक जिसमें 127.0.0.1 के अलावा कई आईपी पते हैं) के मामले का ख्याल नहीं रखता है।

सभी समान नेटवर्क मामलों को पकड़ने के लिए, आपको REMOTE_ADDR के विरुद्ध SERVER_ADDR और सबनेट मास्क का संयोजन जांचना होगा, लेकिन सबनेट मास्क $ _SERVER में उपलब्ध नहीं है।

लेकिन मुझे एक ऐसा फ़ंक्शन मिला जो आप here चाहते हैं। यह कुछ स्क्रीन नीचे है और इसे clientInSameSubnet कहा जाता है। मेरा कोड नहीं, लेकिन सही दिखता है।

+0

$ _SERVER ['SERVER_ADDR'] के विरुद्ध जांच करना एक बुरा विचार है। आरएफसी 1 9 18 अंतरिक्ष में एक vhost होने का मतलब यह नहीं है कि ग्राहक उस स्थान से भी आता है। उदाहरण के लिए, लोड संतुलन निर्माण होते हैं जिसमें एक नोड एक निजी सबनेट में होता है, जबकि लोड बैलेंसर में "सार्वजनिक" आईपी होता है (देखें http://www.linuxvirtualserver.org/VS-NAT.html) – Friek

+1

आपके पास निश्चित रूप से है वहां एक बिंदु, और जैसा कि मैंने कहा, मूर्खतापूर्ण आसान नहीं होने वाला है। लेकिन यह प्रश्न में उद्धृत कोड से बेहतर है, और इसमें आम मामलों को शामिल किया गया है। – Uffe

+0

@Uffe, तो हम PHP से सबनेट मास्क से संबंधित जानकारी कैसे प्राप्त करते हैं? – Pacerier

42

क्या Friek कहा सही है, लेकिन उपलब्ध कराई आप जानते हैं कि कैसे वास्तविक ग्राहक के आईपी प्राप्त करने के लिए, अगर यह एक स्थानीय पता PHP filters का उपयोग कर आप बता सकते हैं:

if (! filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) 
{ 
    // is a local ip address 
} 
+0

यदि असली क्लाइंट आईपी आईपीवी 6 है तो काम नहीं करेगा। –

+0

इसे 2010 से इस समस्या के अनुसार काम करना चाहिए: https://bugs.php.net/bug.php?id=47435 –

+0

127.0.0.1 के लिए यह काम नहीं करेगा – Nikita

3

मामले किसी में मुसीबत उपरोक्त कोड को खोजने गया है , @Uffe द्वारा सुझाए गए, मैंने इसे नीचे शामिल किया है:

<?php 
/** 
* Check if a client IP is in our Server subnet 
* 
* @param string $client_ip 
* @param string $server_ip 
* @return boolean 
*/ 
function clientInSameSubnet($client_ip=false,$server_ip=false) { 
    if (!$client_ip) 
     $client_ip = $_SERVER['REMOTE_ADDR']; 
    if (!$server_ip) 
     $server_ip = $_SERVER['SERVER_ADDR']; 

    // Extract broadcast and netmask from ifconfig 
    if (!($p = popen("ifconfig","r"))) return false; 
    $out = ""; 
    while(!feof($p)) 
     $out .= fread($p,1024); 
    fclose($p); 

    // This is to avoid wrapping. 
    $match = "/^.*".$server_ip; 
    $match .= ".*Bcast:(\d{1,3}\.\d{1,3}i\.\d{1,3}\.\d{1,3}).*"; 
    $match .= "Mask:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/im"; 
    if (!preg_match($match,$out,$regs)) 
     return false; 

    $bcast = ip2long($regs[1]); 
    $smask = ip2long($regs[2]); 
    $ipadr = ip2long($client_ip); 
    $nmask = $bcast & $smask; 

    return (($ipadr & $smask) == ($nmask & $smask)); 
}