【问题标题】:Forbid use of PHP file by unwanted Client-side requests禁止不需要的客户端请求使用 PHP 文件
【发布时间】:2012-12-16 12:07:23
【问题描述】:

我有一个 PHP 文档,比如说 jsonarray.php。

当给定一些参数时,此文件返回关联数组的 json_encode。 我需要禁止不受欢迎的用户出于自己的目的访问和使用此文件。

这可能吗?

另外,我想指定它是一个客户端请求,我在 JavaScript 代码中进行。

【问题讨论】:

  • 参数是怎么给的? GET?
  • 是的,这是一个get请求

标签: php authorization file-access


【解决方案1】:

如果您从另一个 PHP 文件中查看此文件,您可以在此处设置 BASEPATH 常量并在您需要保护的所有文件的顶部添加以下行:

defined('BASEPATH') OR exit('No direct script access allowed');

因此,如果从该特定文件访问该文件,则会设置 BASEPATH 并且一切正常。但是如果某些 url 直接尝试访问,脚本将终止。

如果您从 Javascript 中调用它——其他选项是 将nonce 令牌添加到每个javascript 请求中,这基本上是一个随机生成的对单个请求有效的唯一令牌。有关详细信息,请参阅Cross-Site Request Forgery (CSRF) Prevention Cheat Sheet

这是取自here 的示例:

    function create_api_key(){
        return base64_encode(base64_encode($this->encrypt(time().'X'.$_SERVER['REMOTE_ADDR'])));
    }

    function check_api_key($key,$timeout=5){
        if(empty($key)){ exit('Invalid Key'); }

        $keys=explode('X',$this->decrypt(base64_decode(base64_decode($key))));

        if (isset($key) && isset($keys[0]) && $keys[0] >= (time()-$timeout) &&
        isset($keys[1]) && $keys[1] == $_SERVER['REMOTE_ADDR']){
            return true;
        }else{
            return false;
        }
    }

    function encrypt($value){
        $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
        $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
        return mcrypt_encrypt(MCRYPT_RIJNDAEL_256, 'SECURE_KEY', $value, MCRYPT_MODE_ECB, $iv);
    }

    function decrypt($value){
        $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
        $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
        return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, 'SECURE_KEY', $value, MCRYPT_MODE_ECB, $iv));
    }
}

$csrf = new csrf_check();

if(!empty($_GET['do'])){

    $do = $_GET['do'];
    switch($do){
            //example.com?do=get - a key for the request
        case "get":
            echo $csrf->create_api_key();
            break;

        case "check":
            //key only lasts 30 secs & validate key passed
            //example.com?do=get&key=MEV6NXk4UjVRQXV5Qm1CMjBYa3RZZUhGd2M0YnFBUVF0ZkE5TFpNaElUTT0=
            if(!empty($_GET['key']) && $csrf->check_api_key($_GET['key'],30)){
                exit('Key valid');
            }else{exit('Key invalid');}
            break;

        default:
            exit('Request invalid');
            break;
    }
}

【讨论】:

  • 即使我在我的 JS 中生成了一个nonce,我如何检查它的正确性?我的 php 文件不知道它。 (如果它是一个固定值,那么它是无用的)。可以举个例子吗?
  • 添加了示例代码,您可以使用这个或其中一个PHP CSRF protection libary
  • 好的,我试图实现这个,但是现在我已经完成了我遇到了一些问题:$_SERVER['REMOTE_ADDR'] 不同,因为我在客户端调用 get 并且检查是由服务器执行的.我尝试用字符串更改$_SERVER['REMOTE_ADDR'],但我收到无效的密钥消息。
  • OK,看来一切正常,看了半天我也把请求改成了POST
【解决方案2】:

需要一个特定的 $_GET 参数这样简单的事情可能对你来说就足够了 -

if (isset($_GET['password']) && $_GET['password'] == "your_password"){

}else{
  die('access denied!');
}

现在您只需将密码添加到 URL 中即可访问此 PHP 文件:

http://yourcoolsite.com/jsonarray.php?password=your_password

我建议不要使用“密码”作为参数的键。而是将其称为别的东西,稍微混淆一下,这样就不会立即看出它是密码。

http://yourcoolsite.com/jsonarray.php?mpwyour_password

【讨论】:

  • 这行不通,因为如果我在 JS 中创建一个 getJSON,密码很容易检测到,因为我必须将它作为数据负载中的参数传递
  • @vek - 您需要在您的问题中添加通常是客户端请求的事实...
【解决方案3】:

这可能吗?

没有。

因为当您从 javascript 向该文件发出请求时,浏览器必须可以访问该文件。由于您无法控制浏览器,因此您不能再说浏览器中的 javascript 是否发起了请求或其他东西或其他人。

【讨论】:

  • 您能做的最好的事情就是通过引入一次性令牌的额外复杂性来减慢使用速度。
  • 这对于客户端交互可能会适得其反。最好有经过身份验证的会话。
【解决方案4】:

最简单的方法是使用.htaccess 防止用户直接查看文件 这里有两个链接可以找到方法:Tutorial 1Tutorial 2

【讨论】:

    【解决方案5】:

    为什么不只检查您需要的任何要求,如果不满足,则终止该页面。

    die('Access Blocked');
    

    【讨论】:

    • 因为这不会阻止任何人访问文件。
    • 投反对票有什么原因吗? OP在我回答后改变了问题!
    • @Vektor88 我知道,你还不能,你还没有达到最小值!! ;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-06
    • 1970-01-01
    • 1970-01-01
    • 2015-01-24
    • 1970-01-01
    • 2019-12-10
    相关资源
    最近更新 更多