【问题标题】:Check for Ajax request in CodeIgniter在 CodeIgniter 中检查 Ajax 请求
【发布时间】:2012-07-26 02:17:06
【问题描述】:

我在一个 PHP 脚本中,我想检查请求是否是 Ajax 请求。 (基本上不允许直接脚本访问,除了 Ajax 调用。)

所以,我在 index.php 主文件中的某处定义了 IS_AJAX

define('IS_AJAX', 
       isset($_SERVER['HTTP_X_REQUESTED_WITH']) && 
       strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest');

然后在我的脚本顶部检查它:

if (!IS_AJAX) exit('No direct script access allowed');

由于我是 CodeIgniter 的新手,我想知道:

  • 有没有这样的内置功能?
  • 有更优雅的方法吗?

【问题讨论】:

    标签: php ajax codeigniter


    【解决方案1】:

    您可以使用input 类中的$this->input->is_ajax_request()

    if (!$this->input->is_ajax_request()) {
       exit('No direct script access allowed');
    }
    

    【讨论】:

    • is_ajax_request() 不是安全措施。有一个类似的答案,而是返回 404,这样可以避免给人一种误导的印象。 (HTTP/1.1“当服务器不希望确切地揭示请求被拒绝的原因或没有其他响应时,通常使用此状态码”)stackoverflow.com/questions/6555652/…
    • 我一般都是用load的方式来加载文件,如何防止那些文件直接加载呢?
    【解决方案2】:

    如果您使用hooks (CI docs),则无需为每个 AJAX 方法添加if (!$this->input->is_ajax_request())。这是基于此处的Jorge's solution 并进行了一些细微改进:

    config/config.php

    通过更改默认值启用 CI 挂钩(来自 FALSE):

    $config['enable_hooks'] = TRUE;
    

    config/hooks.php

    在末尾添加以下内容:

    $hook['post_controller_constructor'] = array(
        'class' => 'Ajax_only',
        'function' => 'show_404_on_illegal_ajax',
        'filename' => 'Ajax_only.php',
        'filepath' => 'hooks'
    );
    

    post_controller_constructor:在您的控制器实例化后立即调用,但在任何方法调用发生之前

    config/ajax_methods.php

    创建一个新的配置文件,其中包含仅应在发出 AJAX 请求时调用的所有控制器和方法:

    <?php
    defined('BASEPATH') OR exit('No direct script access allowed');
    /*
    |--------------------------------------------------------------------------
    | References to all AJAX controllers' methods or the controller itself
    |--------------------------------------------------------------------------
    |
    | Based on Jorge's solution: https://stackoverflow.com/a/43484330/6225838
    | Key: controller name
    | Possible values:
    | - array: method name as key and boolean as value (TRUE => IS_AJAX)
    | - boolean: TRUE if all the controller's methods are for AJAX requests
    |
    */
    $config['welcome'] = [
      'index' => FALSE, // or 0 -> this line can be removed (just for reference)
      'ajax_request_method_1' => TRUE, // or 1
      'ajax_request_method_2' => TRUE, // or 1
    ];
    $config['ajax_troller'] = TRUE;
    

    hooks/Ajax_only.php

    创建钩子本身,它检测当前控制器和/或其方法是否存在于上面的新配置文件中。如果是这样,当当前请求不是 AJAX 并且方法/控制器在配置中有 truthy 值时,它会显示 404 默认页面:

    <?php
    defined('BASEPATH') OR exit('No direct script access allowed');
    
    class Ajax_only {
    
      public function __construct()
      {
        $this->CI = &get_instance();
        $this->CI->config->load('ajax_methods');
      }
    
      public function show_404_on_illegal_ajax()
      {
        $fetched_troller_val = $this->CI->config->item(
          $this->CI->router->fetch_class()
        );
        $fetched_method = $this->CI->router->fetch_method();
    
        $is_ajax_method = is_array($fetched_troller_val) &&
            // verify if the method's name is present
            isset($fetched_troller_val[$fetched_method]) &&
            // verify if the value is truthy
            $fetched_troller_val[$fetched_method];
    
        // if the controller is not in the config file then
        // config->item() returned NULL
        if($fetched_troller_val !== NULL &&
            $this->CI->input->is_ajax_request() === FALSE  &&
            ($fetched_troller_val === TRUE || $is_ajax_method)
          ) {
          show_404();
        }
      }
    }
    

    【讨论】:

    • 我认为这是在进行大型项目时实现这一概念的更好方法。
    【解决方案3】:

    如果您想自定义来自您的 codeigniter 应用的请求,请尝试以下操作: 您必须在 application/hooks 文件夹中创建一个名为 Ajax_only.php 的钩子

    class Ajax_only {
        private $_controllers = [];
    
        private $CI;
    
        public function __construct() {
            $this->CI =& get_instance();
        }
    
        public function eval_request() {
            $controller = $this->CI->router->fetch_class();
            $method = $this->CI->router->fetch_method();
            if ( array_key_exists( $controller, $this->_controllers ) && $this->CI->input->is_ajax_request() === FALSE  ) {
                if ( ( $this->_controllers[ $controller ] === TRUE || ( is_array( $this->_controllers[ $controller ] ) && array_key_exists( $method, $this->_controllers[ $controller ] ) && $this->_controllers[ $controller ][ $method ] === TRUE ) ) ) {
                    show_404();
                }
            }
        }
    }
    
    
    /*Examples
     * $_controllers = [
     *      'my_controller_name' => TRUE //all methods must be ajax
     *      'my_controller_name  => [
     *          'method_name' => TRUE //only the selected methods must be ajax
     *      ]
     * ]
     */
    

    并配置你的 application/config/hooks.php 文件

    $hook['post_controller_constructor'] = array(
        'class' => 'Ajax_only',
        'function' => 'eval_request',
        'filename' => 'Ajax_only.php',
        'filepath' => 'hooks'
    );
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-17
    • 1970-01-01
    • 1970-01-01
    • 2017-02-13
    • 2015-05-27
    • 1970-01-01
    相关资源
    最近更新 更多