2012-10-21 16 views
0

我需要限制來自特定域的POST請求。據我所知,HTTP_REFERER檢查不可能是一個很好的解決方案,因爲它可能被欺騙。那麼,當來自不同技術和網絡服務器的兩個不同網站能夠一起工作時,什麼纔是好的解決方案?PHP如何限制域發送POST請求

+0

你的意思是,你只需要一個其他的服務器將允許發送POST請求到您的服務器?您可以使用共享的變異碼系統。 –

+0

有許多解決方案可以將接受的IP地址限制爲使用共享密鑰對有效負載進行簽名。 – Maerlyn

+0

我想允許一些特定的域發送post請求。其實我無法理解如何生成一些隨機密鑰並將其檢入不同的服務器。 – PHPLearner

回答

2

繼承人您可以嘗試通過在表單中​​添加一個隱藏字段(即設置服務器端的會話值)的方法。這樣,如果表單不是源自您的服務器,則會話將不會被設置並且值不匹配。

例子:

<?php 
session_start(); 

if($_SERVER['REQUEST_METHOD']=='POST'){ 
    if(isset($_SESSION['security']) && 
     isset($_SESSION['security_key']) && 
     !empty($_POST[$_SESSION['security_key']]) && 
     $_POST[$_SESSION['security_key']] == $_SESSION['security']) 
    { 
     /* forms post is from domain as session would 
      not have been started and security would not have been set */ 
     echo 'good'; 
    }else{ 
     /* forms post is not from domain */ 
     echo 'bad'; 
    } 
    $_SESSION['security_key'] = sha1(microtime(true)+1); 
    $_SESSION['security'] = sha1(microtime(true)); 
}else{ 
    $_SESSION['security_key'] = sha1(microtime(true)+1); 
    $_SESSION['security'] = sha1(microtime(true)); 
} 
?> 

<form method="POST" action=""> 
    <input type="hidden" name="<?=$_SESSION['security_key'];?>" value="<?=$_SESSION['security'];?>"/> 
    <p><input type="text" name="Text" size="20"><input type="submit" value="Submit"></p> 
</form> 

另外,您可以使用加密,而不是哈希,這樣你可以檢查值:

<?php 
session_start(); 
define('SECURE_KEY',$_SERVER['SERVER_NAME']); 

if($_SERVER['REQUEST_METHOD']=='POST'){ 
    if(isset($_SESSION['security_key']) && isset($_SESSION['security'])){ 
     //Decrypt 
     list($servername,$userip) = explode('X',decrypt(base64_decode($_SESSION['security']))); 

     //Check the decrypted values 
     if($servername == $_SERVER['SERVER_NAME'] && $userip == $_SERVER['REMOTE_ADDR']){ 
      /* forms post is from domain as session would 
      not have been started and security would not have been set */ 
      echo 'good'; 
     }else{ 
      echo 'bad'; 
     } 

    }else{ 
     /* forms post is not from domain */ 
     echo 'bad'; 
    } 

    $_SESSION['security_key'] = sha1(microtime(true)); 
    $_SESSION['security'] = base64_encode(encrypt($_SERVER['SERVER_NAME'].'X'.$_SERVER['REMOTE_ADDR'])); 
}else{ 
    $_SESSION['security_key'] = sha1(microtime(true)); 
    $_SESSION['security'] = base64_encode(encrypt($_SERVER['SERVER_NAME'].'X'.$_SERVER['REMOTE_ADDR'])); 
} 

function encrypt($string, $key = 'PrivateKey', $secret = 'SecretKey', $method = 'AES-256-CBC') { 
    // hash 
    $key = hash('sha256', $key); 
    // create iv - encrypt method AES-256-CBC expects 16 bytes 
    $iv = substr(hash('sha256', $secret), 0, 16); 
    // encrypt 
    $output = openssl_encrypt($string, $method, $key, 0, $iv); 
    // encode 
    return base64_encode($output); 
} 

function decrypt($string, $key = 'PrivateKey', $secret = 'SecretKey', $method = 'AES-256-CBC') { 
    // hash 
    $key = hash('sha256', $key); 
    // create iv - encrypt method AES-256-CBC expects 16 bytes 
    $iv = substr(hash('sha256', $secret), 0, 16); 
    // decode 
    $string = base64_decode($string); 
    // decrypt 
    return openssl_decrypt($string, $method, $key, 0, $iv); 
} 
?> 

<form method="POST" action=""> 
    <input type="hidden" name="<?=$_SESSION['security_key'];?>" value="<?=$_SESSION['security'];?>"/> 
    <p><input type="text" name="Text" size="20"><input type="submit" value="Submit"></p> 
</form> 
+0

它會工作,如果表單是從遠程服務器提交?我的意思是會話價值是相同的? – PHPLearner

+0

遠程服務器?步驟是,用戶點擊您的網站並生成值,表單用其隱藏字段,用戶帖子表單呈現,並且都很好。如果表單來自另一個域,則值不會被創建並且驗證失敗。 –

+0

是的,遠程域名,所以我緊張的安全 – PHPLearner