Как убедить Zend Framework отправлять дублирующиеся заголовки? - PullRequest
0 голосов
/ 23 октября 2018

С заголовками Content-Security-Policy часто возникает необходимость отправить более одного такого заголовка или объединить эти заголовки перед их отправкой.Это связано с тем, что каждый модуль / пакет приложения может определять свой собственный CSP.

В настоящий момент ZF3, похоже, не имеет способа справиться с таким сценарием.Если я пытаюсь добавить несколько заголовков CSP, они перезаписывают друг друга, так что отправляется только последний добавленный заголовок.

Код для воспроизведения проблемы

$headers = $controller->getResponse()->getHeaders();
$headers->addHeader(new ContentSecurityPolicy($someDirectives));
$headers->addHeader(new ContentSecurityPolicy($someOtherDirectives));

Ожидаемые результаты

Ожидаемый результат - ответ с двумя заголовками CSP (ИЛИ CSP, объединенный в объединение).

Фактические результаты

Второе добавление перезаписывает первое, ответ содержит только этого одного CSP.

Вопрос

Как заставить ZF3 отправлять несколько заголовков с одним и тем же именем поля?


Более подробную информацию об этой проблеме см. Также в моей собственной проблеме на github https://github.com/zendframework/zend-http/issues/159

Ответы [ 3 ]

0 голосов
/ 05 ноября 2018

Это принятый стандарт HTTP, и PHP Core поддерживает это.http://php.net/manual/en/function.header.php

Если вы установили заголовки в PHP header("TESTHeader: Test1"); header("TESTHeader: Test2"), только один будет проходить, и это соответствует спецификации RFC2616, раздел 4.2 Стр. 31 & 32

Если вы хотитеотправьте несколько значений, которые ваш заголовок должен создать как header("TESTHeader: Test1, Test2");.хотя можно отправлять несколько заголовков с одинаковыми именами через PHP, это не рекомендуется, так как браузеры и серверы, получающие 2 набора одного и того же заголовка, должны преобразовать их в вышеприведенный стиль, это может вызвать проблемы, так как вы не будете точно знать, в каком формате они находятся. header("TESTHeader: Test1", false); header("TESTHeader: Test2", false).в зависимости от соблюдения сервером или клиентами версии RFC или HTTP.

Таким образом, этот ответ является причиной того, почему вам не разрешено отправлять один и тот же заголовок несколько раз в ZF3, он не может определить, когдаиспользовать перезапись или нет, чтобы в зависимости от вас настройки заголовка.чтобы обойти это и использовать многозначные заголовки, вы можете использовать ответ Джима

0 голосов
/ 05 ноября 2018

создайте свой собственный класс множественного заголовка, добавьте нужную вам функцию (MultipleHeaderInterface), затем добавьте свой заголовок в многоадресную обработку и, наконец, вызовите его в вашем

$headers = $controller->getResponse()->getHeaders();

(вызовите новую функцию с новым fromStringHeaders)

0 голосов
/ 03 ноября 2018

Вы должны иметь возможность создать простой обходной путь, используя GenericMultipleHeader в качестве ссылки (и изменяя запятую на точку с запятой):

class MultiContentSecurityPolicy extends ContentSecurityPolicy implements MultipleHeaderInterface {

    public static function fromString($headerLine)
    {
        list($fieldName, $fieldValue) = GenericHeader::splitHeaderLine($headerLine);
        if (strpos($fieldValue, ';')) {
            $headers = [];
            foreach (explode(';', $fieldValue) as $multiValue) {
                $headers[] = new static($fieldName, $multiValue);
            }
            return $headers;
        } else {
            $header = new static($fieldName, $fieldValue);
            return $header;
        }
    }

    public function toStringMultipleHeaders(array $headers)
    {
        $name  = $this->getFieldName();
        $values = [$this->getFieldValue()];
        foreach ($headers as $header) {
            if (! $header instanceof static) {
                throw new Exception\InvalidArgumentException(
                    'This method toStringMultipleHeaders was expecting an array of headers of the same type'
                );
            }
            $values[] = $header->getFieldValue();
        }
        return $name . ': ' . implode(';', $values) . "\r\n";
    }

}

Затем используйте этот класс вместо ContentSecurityPolicy:

$headers = $controller->getResponse()->getHeaders();
$headers->addHeader(new MultiContentSecurityPolicy($someDirectives));
$headers->addHeader(new MultiContentSecurityPolicy($someOtherDirectives));

Поскольку Zend проверяет интерфейс, а не класс , он должен работать нормально.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...