在 CodeIgniter 中检查 Ajax 请求

2022-08-30 13:28:52

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

所以,我在主文件中的某个地方定义:IS_AJAXindex.php

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的新手,我想知道:

  • 是否有任何这样的内置功能?
  • 有没有更优雅的方法来做到这一点?

答案 1

您可以从输入类中使用:$this->input->is_ajax_request()

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

答案 2

如果使用钩子(CI 文档),则无需向每个 AJAX 方法添加 if (!$this->input->is_ajax_request())。这是基于Jorge的解决方案,并进行了一些细微的改进:

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 并且方法/控制器在配置中具有真实值时,它会显示 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();
    }
  }
}

推荐