Pull to refresh

Как сделать JSON Vulnerability Protection в ответе сервера под Yii2

Reading time2 min
Views5.7K
В AngularJS реализована поддержка JSON Vulnerability Protection, направленная на то, чтобы противодействовать ситуациям, когда злоумышленник может, при определённых условиях, превратить JSON в JSONP и выполнить какой-то код. В качестве меры противодействия на серверной стороне предлагается добавлять к JSON-данным такой префикс: )]}',

Под катом — моя короткая история генерации JSON-данных с префиксом. Но, я думаю, эта история так же хорошо иллюстрирует и более общий вопрос — как можно добавлять свои собственные форматы ответов сервера. В Yii Framework это делается довольно-таки просто — для этого достаточно описать в конфигурации, какой класс будет отвечать за генерацию ответа определённого формата.

Я начал с того, что добавил в конфигурацию (/путь_к_проекту/config/web.php — раздел components → response → formatters) новый тип ответа — «jsonvp», назначив для него класс, который я собираюсь создать.

<?php
// . . .
$config = [
    // . . .
    'components' => [
        // . . .
        'response' => [
            'formatters' => [
                'jsonvp' => 'app\components\JsonVpResponseFormatter',
            ],
        ],
    ],
    // . . .
];


В классе yii\web\Response есть свойство $formatters, которое дополнится тем, что есть в конфигурации. И теперь, если в каком-то экшене задать Yii::$app->response->format = 'jsonvp';, то он будет использовать для форматирования ответа класс app\components\JsonVpResponseFormatter. Во фреймворке есть интерфейс yii\web\ResponseFormatterInterface, который регулирует правила написания таких классов, так что можно применить к моему новому классу этот интерфейс.

<?php
namespace app\components;

use yii\helpers\Json;
use yii\web\Response;
use yii\web\ResponseFormatterInterface;

class JsonVpResponseFormatter implements ResponseFormatterInterface
{
    /**
     * Format as Vulnerability Protected JSON.
     * @param Response $response
     */
    public function format($response)
    {
        $response->getHeaders()->set('Content-Type', 'application/json; charset=UTF-8');
        if ($response->data !== null) {
            $response->content = ")]}',\n" . Json::encode($response->data);
        }
    }
}


Осталось только проверить функционал:

<?php
namespace app\controllers;

use Yii;
use yii\web\Controller;

/**
 * site/* actions.
 * @package app\controllers
 */
class SiteController extends Controller
{
    /**
     * Test JSON output
     * @return array
     */
    public function actionJson()
    {
        Yii::$app->response->format = 'jsonvp';
        return ['123', '456'];
    }
}


При вызове localhost/index.php?r=site/json в браузере выводится такой результат:

)]}',
["123","456"]


Заключение


С помощью такого нехитрого способа можно создавать собственные форматы ответов. Например, как описано выше, — JSON с префиксом, позволяющим защититься от уязвимости. К сожалению, в книге рецептов по фреймворку на текущий момент нет описания того, как создавать собственные форматы ответов, хотя раздел и помечен меткой «TBD». Upd: Уже есть.

Надеюсь, кому-нибудь эта статья будет полезной. Удачи!
Tags:
Hubs:
+10
Comments0

Articles