【问题标题】:PHP How To Restrict domain to send POST request [closed]PHP如何限制域发送POST请求[关闭]
【发布时间】:2012-10-21 14:59:27
【问题描述】:

我需要限制来自特定域的 POST 请求。据我所知,HTTP_REFERER 检查不是一个好的解决方案,因为它可以被欺骗。那么,当来自不同技术和 Web 服务器的两个不同网站一起工作时,什么是好的解决方案呢?

【问题讨论】:

  • 您的意思是,您希望只允许另一台服务器向您的服务器发送 POST 请求?您可以使用共享的变异代码系统。
  • 有许多解决方案,从限制接受的 IP 地址到使用共享密钥对有效负载进行签名。
  • 我想允许一些特定的域发送帖子请求。实际上我无法理解如何生成一些随机密钥并将它们检查到不同的服务器。
  • $_SERVER["REMOTE_ADDR"] 上进行反向 DNS 查找,但您的系统会慢到爬行。
  • 应该更明确地指定...例子等等。

标签: php code-access-security


【解决方案1】:

这是您可以尝试的一种方法,方法是在表单中添加一个隐藏字段,该字段是在服务器端设置的会话值。这样,如果表单不是来自您的服务器,则不会设置会话并且值将不匹配。

例子:

<?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>

【讨论】:

  • 如果表单是从远程服务器提交的,它会起作用吗?我的意思是会话值会相同吗?
  • 远程服务器?步骤将是,用户点击您的网站并生成值,使用隐藏字段呈现表单,用户发布表单,一切都很好。如果表单来自另一个域,则不会创建值并且验证失败。
  • 是的,远程域,所以我对安全性感到紧张
猜你喜欢
  • 1970-01-01
  • 2017-07-13
  • 2011-08-04
  • 2021-01-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多