2011-08-09 8267 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

ここでは自分自身をIPv4に制限しています。今日では、それだけでは不十分です。あなたは a)IPv6でも快適になり、 b)定義のリストを定義します。「ローカル」とは何ですか?本当に192.168。*だけです。独自のIPを持つネットワーク内にいる場合はどうなりますか?または10. *ネットワーク内? – glglgl

+0

[IPが外部であるかどうかを知る方法]の複製可能性(http://stackoverflow.com/questions/14125735/how-to-know-if-an-ip-is-external-or-not) – user956584

答えて

9

いつものように「安全」は難しいかもしれません。

IPv4に制限すると、 "127.0.0.1"をチェックするとlocalhostの大文字と小文字が区別されますが、 "192.168"をチェックします。明らかに間違っています - 16ビットのサブネットマスクを使用して192.168ネットワーク上にあるサーバー上でスクリプトが実行されている場合にのみ機能します。

$ _SERVER ['REMOTE_ADDR']を$ _SERVER ['SERVER_ADDR']と照らし合わせる方が良いでしょう。しかし、これはマルチホームホスト(すなわち、127.0.0.1に加えていくつかのIPアドレスを持つホスト)の場合にも対応していません。

同じネットワークのすべてのケースをキャッチするには、REMOTE_ADDRに対してSERVER_ADDRとサブネットマスクの組み合わせをチェックする必要がありますが、サブネットマスクは$ _SERVERでは使用できません。

しかし、私はあなたがほしいと思う機能をほとんど見つけられませんでした。here。これは、いくつかの画面の下にあり、それはclientInSameSubnetと呼ばれています。私のコードではなく、正しく見える。 Friekが言っ

+0

$ _SERVER ['SERVER_ADDR']をチェックするのは悪い考えです。 rfc1918空間に仮想ホストを持つことは、必ずしもクライアントがその空間から来ることを必ずしも意味しません。たとえば、ノードがプライベートサブネットにあり、ロードバランサに「パブリック」IPがあるロードバランシング構成があります(http://www.linuxvirtualserver.org/VS-NAT.htmlを参照)。 – Friek

+1

私が言ったように、簡単ではないでしょう。しかし、それは質問で引用されたコードよりも優れており、一般的なケースをカバーしています。 – Uffe

+0

@ Uffeだから、PHPからサブネットマスクに関する情報をどのように入手するのですか? – Pacerier

42

は本当ですが、それはPHP filtersを使用してローカルアドレスだ場合、あなたは本当のクライアントのIPを取得する方法を知っていることを提供し、あなたが言うことができます。

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

本当のクライアントIPがIPv6である場合、どちらがうまくいかないでしょうか。 –

+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)); 
} 
関連する問題