5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

リクエストがAjax由来かそれ以外かを識別して、制御をかけたい時ありますよね。

  • セキュリティ上、Ajaxリクエストの場合は排他したい
  • Webアクセスしてほしくないから、Ajaxリクエストのみを許可したい

Symfonyでは、このような要件を簡単に実現できるよう、Requestオブジェクトが組み込まれています。

今回はAjaxリクエストの識別方法を紹介します。

もちろんデモを用意してきました。

Request について

HTTPリクエストに関する情報を保持しているオブジェクトです。
Cookie操作やパラメータ操作など、扱えるデータがめちゃくちゃ多いです。

今回の、Ajax制御で利用するHeader情報等ももちろん操作することができます。

AJAXリクエストの識別方法

isXmlHttpRequest()メソッドが用意されているのでそちらを活用します。

use Symfony\Component\HttpFoundation\Request;

public function myControllerFunction(Request $request)
{
    if ($request->isXmlHttpRequest()) {
        // AJAXリクエストに対する処理
    } else {
        // それ以外のリクエストに対する処理
    }
}

こんな感じで結構シンプルですね。

中の実装までの細かい説明は省きますが、リクエストヘッダーに X-Requested-With: XMLHttpRequest が含まれているかどうかをチェックする感じっぽいです。

実装例

LaravelとDrupalでの実装例を紹介します。

Drupalだったら…。

Routing

{module}/{module}.routing.yml
api.only_ajax:
  path: "/api/only_ajax"
  defaults:
    _controller: "\\Drupal\\custom_api\\Controller\\Calendar::onlyAjax"
api.exclude:
  path: "/api/exclude_ajax"
  defaults:
    _controller: "\\Drupal\\custom_api\\Controller\\Calendar::excludeAjax"

Controller

{module}/src/Controller/ApiController.php
use Drupal\Core\Controller\ControllerBase;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;

class ApiController extends ControllerBase {

  /**
   * Ajax通信のみ許可する.
   *
   * @return \Symfony\Component\HttpFoundation\JsonResponse
   */
public function onlyAjax(Request $request) {
    // Initialized.
    $res = new JsonResponse();

    if ($request->isXmlHttpRequest()) {
        return $res->setJson(json_encode(['message' => 'Please Ajax!!']));
    }
    $products = [
        ['id' => 1, 'name' => 'Product 1', 'price' => 100],
        ['id' => 2, 'name' => 'Product 2', 'price' => 150],
    ];
    return $res->setJson(json_encode($products));
  }

  /**
   * Ajax通信以外を許可する.
   *
   * @return \Symfony\Component\HttpFoundation\JsonResponse
   */
public function excludeAjax(Request $request) {
    // Initialized.
    $res = new JsonResponse();

    if (!$request->isXmlHttpRequest()) {
        return $res->setJson(json_encode(['message' => 'No Ajax!!']));
    }
    $products = [
        ['id' => 1, 'name' => 'Product 1', 'price' => 100],
        ['id' => 2, 'name' => 'Product 2', 'price' => 150],
    ];
    return $res->setJson(json_encode($products));
  }

}

Laravelだったら…。

Routing

routes/web.php
Route::get('/api/only_ajax', [ApiController::class, 'onlyAjax'])->name('api.only_ajax');
Route::get('/api/exclude_ajax', [ApiController::class, 'excludeAjax'])->name('api.exclude_ajax');

Controller

app/Http/Controllers/ApiController.php

class ApiController extends Controller
{
    /**
     * Ajax通信のみ許可する.
     *
     * @return \Symfony\Component\HttpFoundation\JsonResponse
     */
    public function onlyAjax(Request $request)
    {
        // Initialized.
        $res = new JsonResponse();

        if ($request->ajax()) {
            return $res->setJson(json_encode(['message' => 'Please Ajax!!']));
        }
        $products = [
            ['id' => 1, 'name' => 'Product 1', 'price' => 100],
            ['id' => 2, 'name' => 'Product 2', 'price' => 150],
        ];
        return $res->setJson(json_encode($products));
    }

    /**
     * Ajax通信以外を許可する.
     *
     * @return \Symfony\Component\HttpFoundation\JsonResponse
     */
    public function excludeAjax(Request $request)
    {
        // Initialized.
        $res = new JsonResponse();
        if ($request->ajax()) {
            return $res->setJson(json_encode(['message' => 'No Ajax!!']));
        }
        $products = [
            ['id' => 1, 'name' => 'Product 1', 'price' => 100],
            ['id' => 2, 'name' => 'Product 2', 'price' => 150],
        ];
        return $res->setJson(json_encode($products));
    }

}

※ Laravelは標準のRequestオブジェクトを拡張して、ajaxメソッドが用意されているようです。便利 🎉

Laravelの$request→ajax()について

ここで実装されているようです。

Illuminate/Http/Request.php
    /**
     * Determine if the request is the result of an AJAX call.
     *
     * @return bool
     */
    public function ajax()
    {
        return $this->isXmlHttpRequest();
    }

他にも、かなり便利なメソッドが用意されているようです。ぜひのぞいてみてください。

Drupalにも標準でほしい。(あるのかな?)

5
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?