Header php



Послать каждый может. А вот правильно перенаправить – это целое искусство. Но еще труднее дается перенаправление пользователей на нужный путь в интернете. Для этого лучше всего подходит редирект на php.

Что за редирект?

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

В каких случаях может потребоваться редирект:

  • Когда происходит замена движка сайта – в результате этого меняется архитектура всего ресурса. После чего возникает проблема, как сделать редирект;
  • При перекройке структуры ресурса – происходит добавление, удаление или перенос целых разделов или одного материала. Пока происходит этот процесс, временно можно организовать перенаправление пользователя на нужный раздел;

  • Если сайт недавно сменил свое доменное имя – после смены имени домена старое еще некоторое время будет фигурировать в поисковой выдаче. В этом случае редирект пользователя на новый домен будет реализован поисковой системой автоматически;
  • В процессе авторизации – как правило, на большом сайте есть две группы пользователей: обычные посетители и администраторы ресурса. В таком случае имеет смысл реализовать редирект каждого пользователя согласно его правам и роли. После авторизации администратор или модераторы сайта попадают в административную часть ресурса, а посетители – на пользовательскую часть ресурса.

Особенности редиректа на php

В отличие от других языков php обладает некоторыми преимуществами в реализации редиректа:

  • Php является серверным языком программирования. Поэтому перенаправление будет происходить не в html коде страниц, отображаемых в браузере, а в скрипте, размещенном на сервере;
  • Редирект на php может быть реализован несколькими способами. Что во многом расширяет его применение;
  • Благодаря обработке данных на сервере перенаправление, реализованное с помощью php, менее восприимчиво к действию фильтров поисковых систем.

Для редиректа в php используется функция header(). Она применяется для отправки заголовка http. Ее синтаксис:

Принимаемые функцией аргументы:

<ul>
<li><b>string $string</b> – строка заголовка;</li>
</ul>


  • bool $replace – является необязательным атрибутом типа bool. Отвечает за переопределение предыдущего заголовка. Если будет задано true, то предыдущий заголовок или заголовки одного типа будут заменены. Если в аргументе задано false, то перезапись заголовка не состоится. По умолчанию, задано значение true;
  • http_response_code – аргумент принудительно устанавливает код ответа HTTP. Установка кода пройдет успешно при условии, что аргумент string не будет пустым.

При использовании функции header() для редиректа внешних ссылок большое значение имеет место расположения ее вызова. В коде он должен находиться выше всех тегов html:

Применение редиректа header()

Для демонстрации действия функции на локальном сервере нужно создать два файла. Один из них назовем redirect.php, а другой redirect2.php. Внутри первого разместим вызов функции в следующем формате:

В другом файле помещаем строку:

Еще несколько практических примеров использования редиректа на php:

  • Принудительная передача кода состояния http – при использовании первого аргумента функции header() типа «location» по умолчанию в заголовок передается код состояния «302» (временно перемещен). Это может стать проблемой при переносе ресурса на другое доменное имя. В поисковиках такое временное перенаправление может затянуться. Ведь поисковик постоянно анализирует код состояния. А в нем записано «временно перемещен». Пример принудительной перезаписи кода состояния «302» на «301» (постоянно перемещен):

Также перезапись возможна в два этапа. Первая строка производит перезапись кода состояния, а вторая перенаправляет на новый адрес:

  • Использование редиректа внешних ссылок для перенаправления в зависимости от роли пользователя. Роль определяется во время процедуры аутентификации. Значение для обработки записывается в переменную $who:
  • Упрощенный практический пример реализации редиректа внешней ссылки – клик по ссылке ведет на страницу php. Отсюда пользователя через 5 секунд перекидывает на Рамблер. Код html:

Код файла redirect3.php:

Ну, вот мы и научились основам редиректа на php. Теперь можно смело браться за перенаправление пользователей в нужное русло. Главное не ошибиться в направлении, а то приведете всех своих юзеров на чужой сайт…

www.internet-technologies.ru

В соответствии со спецификацией http, этот протокол поддерживает передачу служебной информации от сервера к броузеру, оформленной в виде специальных заголовков.

Таким образом, http headers — это средство общения сервера с удаленным клиентом. Каждый заголовок обычно состоит из одиночной линии ascii текста с именем и значением. Сами заголовки никак не отображаются в окне броузера, но зачастую могут сильно изменить отображение сопутствующего документа.


Механизм отправки http заголовков в php.
Механизм отправки заголовков в php представлен функцией header(). Особенность протокола http заключается в том, что заголовок должен быть отправлен до посылки других данных, поэтому функция должна быть вызвана в самом начале документа и должна выглядеть следующим образом:

header("http заголовок"[, replace]);

Необязательный параметр replace может принимать значения (true или false) и указывает на то, должен ли быть заменен предыдущий заголовок подобного типа, либо добавить данный заголовок к уже существующему.

В отношении функции header() часто применяется функция headers_sent(), которая в качестве результата возвращает true в случае успешной отправки заголовка и false в обратном случае.

Рассмотрим наиболее используемые http заголовки.

Cache-control

"cache-control: " значение

Заголовок управления кешированием страниц. Вообще, данная функция является одной из самых распространенных в использовании заголовков.

    Данный заголовок может быть использован со следующими значениями:

  • no-cache — Запрет кеширования. Используется в часто обновляемых страницах и страницах с динамическим содержанием. Его действие подобно meta тегу «pragma: no-cache».

  • public — Разрешение кеширования страницы как локальным клиентом, так и прокси-сервером.
  • private — Разрешение кеширования только локальным клиентом.
  • max-age — Разрешение использования кешированного документа в течение заданного времени в секундах.
  • no-store — Cтраница содержит приватные данные, сохранять в кэше нельзя!
// Кеширование локальными клиентами и использование в течение 1 часа header("cache-control: private, max-age = 3600"); echo "<h1>", date("H:i:s"), "</h1>";

// кеширования всеми серверами на 1 час header("Cache-Control: public"); header("Expires: " . date("r", time() + 3600)); echo "<h1>", date("H:i:s"), "</h1>";

Совсем жесткий запрет кеширования на всех этапах:

header("Cache-Control: no-store, no-cache, must-revalidate"); header("Expires: " . date("r")); echo "<h1>", date("H:i:s"), "</h1>";

Кеширование с помощью файла .htaccess

Expires

"expires: " http-date


Устанавливает дату и время, после которого документ считается устаревшим. Дата должна указываться в следующем формате (на английском языке):

День недели (сокр.) число (2 цифры) Месяц (сокр.) год часы:минуты:секунды gmt

Например, fri, 09 jan 2002 12:00:00 gmt

Текущее время в этом формате возвращает функция gmdate() в следующем виде:

echo gmdate("d, d m y h:i:s")." gmt";

Возможно использование данного http заголовка для запрета кеширования. Для этого необходимо указать прошедшую дату. Иногда можно встретить и такую комбинацию Expires: now

Last-modified

last-modified: http-date

Указывает дату последнего изменения документа. Дата должна задаваться в том же формате, что и в случае с заголовком expires. Данный заголовок можно не использовать для динамических страниц, так как многие серверы (например, apache) для таких страниц сами выставляют дату модификации.

При запросе это значение передаётся клиентом в специальном заголовке запроса: If-Modified-Since. Обработчик запроса может проверить, изменился ли объект, и если нет — вернуть ответ с пустым телом и кодом ответа 304 Not Modified. Само содержимое страницы не передаётся, и клиент будет использовать то содержимое, которое хранится у него в кэше.

Возможно сделать страницу всегда обновленной:

header("last-modified: ".gmdate("d, d m y h:i:s")." gmt");  

Пример использования кеширования с помощью Last-modified

ETag

ETag’и (Entity Tags — тэги сущностей) — механизм, который используют браузеры и веб-сервера, чтобы определить, является ли объект, находящийся в кэше браузера таким же, как соответствующий объект на сервере (а Entity (сущность) — другое название того, что мы называем компонентами: картинки, скрипты и т.д.). Тэги сущностей были задуманы как механизм для определения актуальности сущности в кэше браузера, что является более гибким подходом, нежели проверка по дате последнего изменения (last-modified). ETag — это строка, которая однозначно идентифицирует конкретную версию компонента. Единственное требование: строка должна быть заключена в двойные кавычки. Сервер указывает ETag для компонента используя HTTP-заголовок ETag:

 HTTP/1.1 200 OK Last-Modified: Tue, 12 Dec 2006 03:03:59 GMT ETag: "10c24bc-4ab-457e1c1f" Content-Length: 12195 

Позднее, если браузер хочет определить актуальность компонента, он передает заголовок If-None-Match для передачи ETag’а обратно на сервер. Если ETag’и совпадают, ответ от сервера приходит со статус-кодом 304, уменьшая таким образом объем передачи на 12195 байт:

 GET /i/yahoo.gif HTTP/1.1 Host: us.yimg.com If-Modified-Since: Tue, 12 Dec 2006 03:03:59 GMT If-None-Match: "10c24bc-4ab-457e1c1f" HTTP/1.1 304 Not Modified 

Включить ETag для Apache можно, например, следующей директивой:

 FileETag MTime Size 

Открючить ETag для Apache:

 FileETag none 

Location

"location :" абсолютный url


Полезный заголовок, который перенаправляет броузер на указанный адрес. Его действие сравнимо с meta тегом refresh:

header("location: http://htmlweb.ru");

Например, этот заголовок может быть использован так:

if ($login != $admin_login) header("location: http://www.server.com/login.php"); else header("location: http://www.server.com/admin.php?login=$login"); if (!headers_sent()) exit("Произошла ошибка! Пройдите авторизацию заново");

Content-type

Content-type : MIME тип возвращаемого документа

header("Content-type: text/html");

Content-length

Content-length : размер возвращаемого документа

Status

Status : MIME тип возвращаемого документа Эта директива используется для задания серверу HTTP/1.0 строки-статус, которая будет послана клиенту. Формат: nnn xxxxx, где nnn — 3-х цифровой статус-код, и xxxxx строка причины, например: «Forbidden» (Запрещено). Http-коды статусов.

header("http/1.0 200 Ok");  

Content-Encoding

Content-Encoding : gzip Способность принимать сжатое содержимое клиент отправляет серверу с помощью заголовка Accept-Encoding: gzip. Обычно сервер указывает Accept-Encoding: gzip,deflate.

Range

Задать диаппазон скачиваемой информации

header("Range: bytes=1024-");

Разрешить кросс-доменные запросы

header('Access-Control-Allow-Origin: *'); header('Access-Control-Max-Age: 600'); // время в секундах кеширования разрешения

При использовании .htaccess:

<IfModule mod_headers.c>  Header set Access-Control-Allow-Origin "*" </IfModule>

Подробнее см. http://www.w3.org/TR/cors/#access-control-allow-origin-response-hea

X-XSS-Protection

Атака XSS (межсайтовый скриптинг) это тип атаки, при котором вредоносный код может быть внедрён в атакуемую страницу.

Например вот так:

<h1>Hello, <script>alert('hacked')</script></h1>

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

И заголовок X-XSS-Protection управляет этим поведением браузера.

Принимаемые значения:


  • 0 фильтр выключен
  • 1 фильтр включен. Если атака обнаружена, то браузер удалит вредоносный код.
  • 1; mode=block. Фильтр включен, но если атака обнаружится, страница не будет загружена браузером.
  • 1; report=http://domain/url. фильтр включен и браузер очистит страницу от вредоносного кода, при этом сообщив о попытке атаки. Тут используется функция Chromium для отправки отчёта о нарушении политика защиты контента (CSP) на определённый адрес.

Создадим веб сервер-песочницу на node.js, чтобы посмотреть как это работает.

var express = require('express')  var app = express()   app.use((req, res) => {  if (req.query.xss) res.setHeader('X-XSS-Protection', req.query.xss)  res.send(`<h1>Hello, ${req.query.user || 'anonymous'}</h1>`)  })   app.listen(1234)

Буду использовать Google Chrome 55.

Без заголовка
http://localhost:1234/?user=%3Cscript%3Ealert(%27hacked%27)%3C/script%3E

Ничего не произойдёт, браузер успешно заблокирует атаку. Chrome, по умолчанию, блокирует угрозу и сообщает об этом в консоли.

X-XSS-Protection: 0
http://localhost:1234/?user=%3Cscript%3Ealert(%27hacked%27)%3C/script%3E&xss=0

О нет!

X-XSS-Protection: 1
http://localhost:1234/?user=%3Cscript%3Ealert(%27hacked%27)%3C/script%3E&xss=1

Страница была очищена из-за явного указания заголовка.

X-XSS-Protection: 1; mode=block
http://localhost:1234/?user=%3Cscript%3Ealert(%27hacked%27)%3C/script%3E&xss=1;%20mode=block

В этом случае атака будет предотвращена путём блокирования загрузки страницы.

X-XSS-Protection: 1; report=http://localhost:1234/report
http://localhost:1234/?user=%3Cscript%3Ealert(%27hacked%27)%3C/script%3E&xss=1;%20report=http://localhost:1234/report

Атака предотвращена и сообщение об этом отправлено по соответствующему адресу.

X-Frame-Options

При помощи данного заголовка можно защититься от так называемого Кликджекинга [Clickjacking].

Представьте, что у злоумышленника есть канал на YouTube и ему хочется больше подписчиков.

Он может создать страницу с кнопкой «Не нажимать», что будет значить, что все на неё обязательно нажмут. Но поверх кнопки находится абсолютно прозрачный iframe и в этом фрейме прячется страница канала с кнопкой подписки. Поэтому при нажатии на кнопку, на самом деле пользователь подписывается на канал, если конечно, он был залогинен в YouTube.

Продемонстрируем это.

Сперва нужно установить расширение для игнорирования данного заголовка.

Создадим простую страницу.

<style> button { background: red; color: white; padding: 10px 20px; border: none; cursor: pointer; } iframe { opacity: 0.8; z-index: 1; position: absolute; top: -570px; left: -80px; width: 500px; height: 650px; } </style>  <button>Do not click his button!</button> <iframe src="https://youtu.be/dQw4w9WgXcQ?t=3m33s"></iframe>

Как можно заметить, я разместил фрейм с подпиской прям над кнопкой (z-index: 1) и поэтому если попытаться на неё нажать, то на самом деле нажмётся фрейм. В этом примере фрейм не полностью прозрачен, но это исправляется значением opacity: 0.

На практике, такое не сработает, потому что у YouTube задан нужный заголовок, но смысл угрозы, надеюсь, понятен.

Для предотвращения страницы быть использованной во фрейме нужно использовать заголовок X-Frame-Options.

Принимаемые значения:

  • deny не загружать страницу вообще.
  • sameorigin не загружать, если источник не совпадает.
  • allow-from: ДОМЕН можно указать домен, с которого страница может быть загружена во фрейме.

Нам понадобится веб сервер для демонстрации

var express = require('express')   for (let port of [1234, 4321]) {  var app = express()  app.use('/iframe', (req, res) => res.send(`<h1>iframe</h1><iframe src="//localhost:1234?h=${req.query.h || ''}"></iframe>`))  app.use((req, res) => {  if (req.query.h) res.setHeader('X-Frame-Options', req.query.h)  res.send('<h1>Website</h1>')  })  app.listen(port)  }
Без заголовка

Все смогут встроить наш сайт по адресу localhost:1234 во фрейм.

X-Frame-Options: deny

Страницу вообще нельзя использовать во фрейме.

X-Frame-Options: sameorigin

Только страницы с одинаковым источником смогут встраивать во фрейм. Источники совпадают, если домен, порт и протокол одинаковые.

X-Frame-Options: allow-from localhost:4321

Похоже, что Chrome игнорирует такую опцию, т.к. существует заголовок Content-Security-Policy (о ней будет рассказано ниже). Не работает это и в Microsoft Edge.

X-Content-Type-Options

Данный заголовок предотвращает атаки с подменой типов MIME (<script src=»script.txt»>) или несанкционированного хотлинка (<script src=»https://raw.githubusercontent.com/user/repo/branch/file.js»>)

var express = require('express') var app = express()  app.use('/script.txt', (req, res) => {  if (req.query.h) res.header('X-Content-Type-Options', req.query.h)  res.header('content-type', 'text/plain')  res.send('alert("hacked")')  })   app.use((req, res) => {  res.send(`<h1>Website</h1><script src="/script.txt?h=${req.query.h || ''}"></script>`) })  app.listen(1234)
Без заголовка
http://localhost:1234/

Хоть script.txt и является текстовым файлом с типом text/plain, он будет запущен как скрипт.

X-Content-Type-Options: nosniff
http://localhost:1234/?h=nosniff

На этот раз типы не совпадают и файл не будет исполнен.

Content-Security-Policy

Это относительно молодой заголовок и помогает уменьшить риски атаки XSS в современных браузерах путём указания в заголовке какие именно ресурсы могут подргружаться на странице.

Например, можно попросить браузер не исполнять inline-скрпиты и загружать файлы только с одного домена. Inline-скрпиты могут выглядеть не только как <script>…</script>, но и как <h1 onclick=»…»>.

Посмотрим как это работает.

var request = require('request')  var express = require('express')   for (let port of [1234, 4321]) {  var app = express()  app.use('/script.js', (req, res) => {  res.send(`document.querySelector('#${req.query.id}').innerHTML = 'изменено ${req.query.id}-скриптом'`)  })  app.use((req, res) => {  var csp = req.query.csp  if (csp) res.header('Content-Security-Policy', csp)  res.send(`  <html>  <body>  <h1>Hello, ${req.query.user || 'anonymous'}</h1>  <p id="inline">это будет изменено inline-скриптом?</p>  <p id="origin">это будет изменено origin-скриптом?</p>  <p id="remote">это будет изменено remote-скриптом?</p>  <script>document.querySelector('#inline').innerHTML = 'изменено inline-скриптом'</script>  <script src="/script.js?id=origin"></script>  <script src="//localhost:1234/script.js?id=remote"></script>  </body>  </html>  `)  })  app.listen(port)  }
Без заголовка

Это работает так, как вы и ожидали

Content-Security-Policy: default-src ‘none’
http://localhost:4321/?csp=default-src%20%27none%27&user=%3Cscript%3Ealert(%27hacked%27)%3C/script%3E

default-src применяет правило для всех ресурсов (картинки, скрипты, фреймы и т.д.), значение ‘none’ блокирует всё. Ниже продемонстрировано что происходит и ошибки, показываемые в браузере.

Chrome отказался запускать любые скрипты. В таком случае не получится даже загрузить favicon.ico.

Content-Security-Policy: default-src ‘self’
http://localhost:4321/?csp=default-src%20%27self%27&user=%3Cscript%3Ealert(%27hacked%27)%3C/script%3E

Теперь можно использовать ресурсы с одного источника, но по прежнему нельзя запускать внешние и inline-скрипты.

Content-Security-Policy: default-src ‘self’; script-src ‘self’ ‘unsafe-inline’
http://localhost:4321/?csp=default-src%20%27self%27;%20script-src%20%27self%27%20%27unsafe-inline%27&user=%3Cscript%3Ealert(%27hacked%27)%3C/script%3E

На этот раз мы разрешили исполнение и inline-скриптов. Обратите внимание, что XSS атака в запросе тоже была заблокирована. Но этого не произойдёт, если одновременно поставить и unsafe-inline, и X-XSS-Protection: 0.

Другие значения

На сайте content-security-policy.com красиво показаны множество примеров.

  • default-src ‘self’ разрешит ресурсы только с одного источника
  • script-src ‘self’ www.google-analytics.com ajax.googleapis.com разрешит Google Analytics, Google AJAX CDN и ресурсы с одного источника.
  • default-src ‘none’; script-src ‘self’; connect-src ‘self’; img-src ‘self’; style-src ‘self’; разрешит изображения, скрипты, AJAX и CSS с одного источника и запретит загрузгу любых других ресурсов. Для большинства сайтов это хорошая начальная настройка.

Я этого не проверял, но я думаю, что следующие заголовки эквиваленты:

  • frame-ancestors ‘none’ и X-Frame-Options: deny
  • frame-ancestors ‘self’ и X-Frame-Options: sameorigin
  • frame-ancestors localhost:4321 и X-Frame-Options: allow-from localhost:4321
  • script-src ‘self’ без ‘unsafe-inline’ и X-XSS-Protection: 1

Если взглянуть на заголовки facebook.com или twitter.com, то можно заметить, что эти сайты используют много CSP.

Strict-Transport-Security

HTTP Strict Transport Security (HSTS) это механизм политики безопасности, который позволяет защитить сайт от попытки небезопасного соединения.

Допустим, что мы хотим подключиться к facebook.com. Если не набрать перед запросом https://, то протокол, по умолчанию, будет выбран HTTP и поэтому запрос будет выглядеть как http://facebook.com.

$ curl -I facebook.com  HTTP/1.1 301 Moved Permanently  Location: https://facebook.com/

После этого мы будем перенаправлены на защищённую версию Facebook.

Если подключиться к публичной WiFi точке, которая принадлежит злоумышленнику, то запрос может быть перехвачен и вместо facebook.com злоумышленник может подставить похожую страницу, чтобы узнать логин и пароль.

Чтобы обезопаситься от такой атаки, можно использовать вышеупомянутый заголовок, который скажет клиенту в следующий раз использовать https-версию сайта.

$ curl -I https://www.facebook.com/  HTTP/1.1 200 OK  Strict-Transport-Security: max-age=15552000; preload

Если пользователь был залогинен в Facebook дома, а потом попытался открыть его из небезопасной точки доступа, то ему ничего не угрожает, т.к. браузеры запоминают этот заголовок.

Но что будет, если подключиться в небезопасной сети первый раз? В этом случае защититься не получится.

Но у браузеров есть козырь и на этот случай. В них есть предопределённый список доменов, для которых следует использовать только HTTPS.

Можно отправить свой домен по этому адресу. Там также можно узнать правильно ли используется заголовок.

Принимаемые значения:

  • max-age=15552000 время, в секундах, которое браузер должен помнить о заголовке.
  • includeSubDomains Если указать это опциональное значение, то заголовок распространяется и на все поддомены.
  • preload если владелец сайта хочет, чтобы домен попал в предопределённый список, поддерживаемый Chrome (и используемый Firefox и Safari).

А если потребуется переключиться на HTTP перед сроком истечения max-age или если установлен preload? Можно поставить значение max-age=0 и тогда правило перехода на https версию работать перестанет.

Public-Key-Pins

HTTP Public Key Pinning (HPKP) это механизм политики безопасности, который позволяет HTTPS сайтам защититься от использования злоумышленниками поддельных или обманных сертификатов.

Принимаемые значения:

  • pin-sha256=»<sha256>» в кавычках находится закодированный с помощью Base64 отпечаток Subject Public Key Information (SPKI). Можно указать несколько пинов для различных открытых ключей. Некоторые браузеры в будущем могут использовать и другие алгоритмы хеширования, помимо SHA-256.
  • max-age=<seconds> время, в секундах, которое браузер запоминает что для доступа к сайту нужно использовать только перечисленные ключи.
  • includeSubDomains если указать этот необязательный параметр, то заголовок действует и на все поддомены.
  • report-uri=»<URL>» если указать URL, то при ошибке проверки ключа, соответствующее сообщение отправится по указанному адресу.

Вместо заголовка Public-Key-Pins можно использовать Public-Key-Pins-Report-Only, в таком случае будут отправляться только сообщения об ошибках совпадения ключей, но браузер всё равно будет загружать страницу.

Так делает Facebook:

$ curl -I https://www.facebook.com/  HTTP/1.1 200 OK  ...  Public-Key-Pins-Report-Only:  max-age=500;  pin-sha256="WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18=";  pin-sha256="r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E=";  pin-sha256="q4PO2G2cbkZhZ82+JgmRUyGMoAeozA+BSXVXQWB8XWQ=";  report-uri="http://reports.fb.com/hpkp/"

Зачем это нужно? Не достаточно ли доверенных центров сертификации (CA)?

Злоумышленник может создать свой сертификат для facebook.com и путём обмана заставить пользователя добавить его в своё хранилище доверенных сертификатов, либо он может быть администратором.

Попробуем создать сертификат для facebook.

sudo mkdir /etc/certs  echo -e 'USnCAnSFnFBnXXnwww.facebook.comnno@spam.org' |   sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048   -keyout /etc/certs/facebook.key   -out /etc/certs/facebook.crt

И сделать его доверенным в локальной системе.

# curl  sudo cp /etc/certs/*.crt /usr/local/share/ca-certificates/  sudo update-ca-certificates  # Google Chrome  sudo apt install libnss3-tools -y  certutil -A -t "C,," -n "FB" -d sql:$HOME/.pki/nssdb -i /etc/certs/facebook.crt  # Mozilla Firefox  #certutil -A -t "CP,," -n "FB" -d sql:`ls -1d $HOME/.mozilla/firefox/*.default | head -n 1` -i /etc/certs/facebook.crt

А теперь запустим веб сервер, использующий этот сертификат.

var fs = require('fs')  var https = require('https')  var express = require('express')   var options = {  key: fs.readFileSync(`/etc/certs/${process.argv[2]}.key`),  cert: fs.readFileSync(`/etc/certs/${process.argv[2]}.crt`)  }   var app = express()  app.use((req, res) => res.send(`<h1>hacked</h1>`))  https.createServer(options, app).listen(443)

Переключимся на сервер

echo 127.0.0.1 www.facebook.com | sudo tee -a /etc/hosts  sudo node server.js facebook

Посмотрим что получилось

$ curl https://www.facebook.com  <h1>hacked</h1>

Отлично. curl подтверждает сертификат.

Так как я уже заходил на Facebook и Google Chrome видел его заголовки, то он должен сообщить об атаке но разрешить страницу, так?

Неа. Ключи не проверялись из-за локального корневого сертификата [Public-key pinning bypassed]. Это интересно…

Хорошо, а что насчёт www.google.com?

echo -e 'USnCAnSFnGooglenXXnwww.google.comnno@spam.org' |   sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048   -keyout /etc/certs/google.key   -out /etc/certs/google.crt  sudo cp /etc/certs/*.crt /usr/local/share/ca-certificates/  sudo update-ca-certificates  certutil -A -t "C,," -n "Google" -d sql:$HOME/.pki/nssdb -i /etc/certs/google.crt  echo 127.0.0.1 www.google.com | sudo tee -a /etc/hosts  sudo node server.js google

Тот же результат. Думаю это фича.

Но в любом случае, если не добавлять эти сертификаты в локальное хранилище, открыть сайты не получится, потому что опции продолжить небезопасное соединение в Chrome или добавить исключение в Firefox не будет.

Content-Encoding: br

Данные сжаты при помощи Brotli.

Алгоритм обещает лучшее сжатие чем gzip и сравнимую скорость разархивирования. Поддерживается Google Chrome.

Разумеется, для него есть модуль в node.js.

var shrinkRay = require('shrink-ray')  var request = require('request')  var express = require('express')   request('https://www.gutenberg.org/files/1342/1342-0.txt', (err, res, text) => {  if (err) throw new Error(err)  var app = express()  app.use(shrinkRay())  app.use((req, res) => res.header('content-type', 'text/plain').send(text))  app.listen(1234)  })

Исходный размер: 700 Кб
Brotli: 204 Кб
Gzip: 241 Кб

Timing-Allow-Origin

С помощью Resource Timing API можно узнать сколько времени заняла обработка ресурсов на странице.

Поскольку информация о времени загрузки может быть использована чтобы определить посещал ли пользователь страницу до этого (обращая внимание на то, что ресурсы могут кэшироваться), стандарт считается уязвимым, если давать такую информацию любым хостам.

<script> setTimeout(function() {  console.log(window.performance.getEntriesByType('resource')) }, 1000) </script>  <img src="http://placehold.it/350x150"> <img src="/local.gif">


Похоже, если не указать Timing-Allow-Origin, то получить детальную информацию о времени операций (поиска домена, например) можно только для ресурсов с одним источником.

Использовать можно так:

  • Timing-Allow-Origin: *
  • Timing-Allow-Origin: http://foo.com http://bar.com

Alt-Svc

Альтернативные Сервисы [Alternative Services] позволяют ресурсам находиться в различных частях сети и доступ к ним можно получить с помощью разных конфигураций протокола.

Такой используется в Google:

  • alt-svc: quic=»:443″; ma=2592000; v=«36,35,34»

Это означает, что браузер, если захочет, может использовать QUIC, это HTTP над UDP, через порт 443 следующие 30 дней (ma = 2592000 секунд, или 720 часов, т.е 30 дней). Понятия не имею что означает параметр v, версия?

htmlweb.ru

Для тех, кто только начинает изучать PHP — заголовки HTTP явля.тся каким-то туманом, который почему-то не особо приятный…давайте его рассеивать…

Вообще нужно сказать, что заголовки HTTP используются для общения между браузером и веб-сервером. То есть один говорить в каком формате принимает, другой в каком передает.

В PHP для передачи заголовков используется функция header() — основное внимание ей.

void header ( string string [, bool replace [, int http_response_code]] )

!!! — главное — перед этой функцией(то есть перед отправкой заголовков) — не должно стоять ни пробелов, ни других html тегов, иначе будет ошибка!

1) Вообще их можно узнать через функцию: var_dump(getallheaders());

Узнать операционку пользователя и версию браузера можно так:

$headers = getallheaders();
echo $headers['User-Agent'];

Но чаще пользуются суперглобальным массивом $_SERVER для этих нужд.

2) А узнать то, что отправили можно так, через функцию headers_list():

header("Человек: это звучит гордо!");
var_dump(headers_list());

 

Как использовать

1) Для переадрессации на другой сайт. Вы скорее всего видели в своей жизни неоднократно, заходишь на свой сайт, а он перекидывает тебя на другой, так вот это и есть применение заголовков таким образом:

header( 'Location: http://saitsozdanie.ru/' );

или перекинь меня пожалуйста, через 5 секунд после захода:

header( 'Refresh: 5; url=http://saitsozdanie.ru/' );  (то же самое но с помощью html тегов <meta http-equiv="refresh" content="5;http://saitsozdanie.ru/ />)

2) Для установки кодировки сайта:

header('Content-Type: text/html; charset=utf-8');

или тоже самое html тегом:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

Основная боязнь у новичков — именно от незнания, то в одном виде видят, то в другом. Так вот знайте, что можно и так и так! Все должно стать легче!)

3) Для отработки ошибок:

//Страница выполнена корректно
header( 'HTTP/1.1 200 OK' );
//Запрашиваемая страница не найдена
header( 'HTTP/1.1 404 Not Found' );
//Доступ запрещен:
header( 'HTTP/1.1 403 Forbidden' );
//Страница перемещена навсегда.
//Используется для корректировки урлов поисковых серверов.
header( 'HTTP/1.1 301 Moved Permanently' );
//Сервер выполнил скрипт с ошибкой
header( 'HTTP/1.1 500 Internal Server Error' );

4) Установка типа контента — что мы передаем рисунок — это одно, если pdf файл — то другой заголовок и тд:

header('Content-Type: text/plain'); // plain text файл
header('Content-Type: image/jpeg'); // JPG картинка в формате
header('Content-Type: audio/mpeg'); // Audio MPEG (MP3,...) файл
header('Content-Type: application/x-shockwave-flash'); // Flash animation

5) Когда последний раз изменялось содержимое контента:

header( 'Last-Modified: '.gmdate( 'D, d M Y H:i:s', ( time() - 60 ) ).' GMT' );

6) Заголовок на PHP для отключения кэширования:

header( 'Cache-Control: no-cache, no-store, max-age=0, must-revalidate' );
header( 'Expires: Mon, 1 Apr 2001 01:02:03 GMT' );
header( 'Pragma: no-cache' );

7) Задаем язык:

header( 'Content-language: en' ); // en = English

 

Также заголовки используются:

  • для задания куки;

 

 

 

saitsozdanie.ru

blog.bullgare.com

Статьи -> Программирование -> PHP

Отправка сырого HTTP-заголовка. PHP функция header

v:1.0 27.01.2010

Перевод официальной документации.

(PHP 4, PHP 5)

header — отправляет сырой HTTP-заголовок.

Описание

void header(string $string [, bool $replace = true [, int $http_response_code]])
Функция header() используется для отправки сырого (необработанного) HTTP заголовка. Дополнительную информацию о заголовке HTTP смотрите в спецификации HTTP/1.1

Помните, что функция header() должна вызываться до любой другой директивы, например обычного тега HTML, пустой строки в файле или PHP-формы. Очень часто встречается ошибка, когда перед функцией header() вызываются функции include(), require() или другие функции для доступа к файлам, или вставляются пустые строки и пробелы.
Эта же проблема появляется, при использовании единых файлов PHP/HTML.

Пример
<html>
<?php
/* Этот код вернет ошибку, т.к. до вызова header() встречается тег HTML*/
header('Location: http://www.example.com/');
?>

Параметры

string

Строка заголовка.

Возможны два варианта вызова функции header().
Первый вариант — вызов функции со строкой (параметр string) "HTTP" (регистр не имеет значения), которая укажет код HTTP статуса. Например, если Вы в Apache сконфигурировали PHP-скрип для обработки ошибки типа «запрашиваемый файл не найден» (директива ErrorDocument), то у Вас есть возможность убедиться, что Ваш скрипт генерирует правильный код статуса.

<?php
header("HTTP/1.0 404 Not Found");
?>

Второй вариант вызова — использование в заголовке строки "Location:".
В этом случае функция не только возвращает заголовок в браузер, но и возвращает код статуса REDIRECT (302), если уже не установлен код 201 или 3xx

<?php
header("Location: http://www.example.com"); /* Перенаправление браузера */

/* Убедитесь, что последующий код не выполняется после перенаправления*/
exit;
?>

replace

Необязательный параметр replace (замена) определяет надо ли заменить предыдущий похожий заголовок или добавить следующий того же типа. По умолчанию заголовок будет заменен. Однако, если Вы передадите значение FALSE, то можете создать несколько заголовков одного типа.
Например:

<?php
header('WWW-Authenticate: Negotiate');
header('WWW-Authenticate: NTLM'false);
?>

http_response_code

Принудительная установка значения HTTP код ответа.

Возвращаемые значения

Функция не возвращает никакие значения.

Хронология изменений

Версия Описание
4.4.2 и 5.1.2 Устранена возможность отправки нескольких заголовков за раз, это позволило повысить защиту от инъекционных атак (injection attacks)
4.3.0 Добавлен параметр http_response_code
4.0.4 Добавлен параметр replace

Примеры

Пример #1 Диалог загрузки

Если вы хотите сообщить пользователю, какого типа данные отправляете (например сгенерированный PDF файл ), то можете использовать заголовок Content-Disposition, в котором будут указаны предлагаемое имя файла и команда браузеру отрисовать диалог сохранения файла.

<?php
//Высылается файл PDF
header('Content-type: application/pdf');

//Файл будет назван downloaded.pdf
header('Content-Disposition: attachment; filename="downloaded.pdf"');

//Исходный PDF файл называется original.pdf
readfile('original.pdf');
?>

Пример #2 Кэширование директив

Скрипты PHP часто генерируют динамическое содержание, которое не должно быть кэшировано клиентским браузером или какими-либо прокси между сервером и клиентским браузером. Во многих браузерах и клиентах можно принудительно отключить механизм кэширования, следующим образом:

<?php
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); //Дата в прошлом
?>

Примечание: Вы можете обнаружить, что Ваши страницы не кэшруются даже если Вы не выполнили приведенные выше функции. Пользователь может поменять настройки браузера и таким образом изменить работу механизма кэширования.
Отправив приведенные выше заголовки, вы перекроете любые настройки, которые могут управлять кэшированием страниц.
И еще пара слов… Если используются сессии, с помощью конфигурационных параметров session_cache_limiter() и session.cache_limiter можно настроить корректную генерацию кэш-ориентированных заголовков.

www.smartyit.ru

Примечания

Замечание:

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

Замечание:

Чтобы обойти эту проблему, можно буферизовать вывод скрипта. В этом случае все выводимые данные будут буферизоваться на сервере, пока не будет дана явная команда на пересылку данных. Управлять буферизацией можно вручную функциями ob_start() и ob_end_flush(), либо задав директиву output_buffering в конфигурационном файле php.ini, или же настроив соответствующим образом конфигурацию сервера.

Замечание:

Строка заголовка состояния HTTP всегда будет отсылаться клиенту первой, вне зависимости от того был соответствующий вызов функции header() первым или нет. Это состояние можно перезаписать, вызывая header() с новой строкой состояния в любое время, когда можно отправлять HTTP-заголовки.

Замечание:

В Microsoft Internet Explorer 4.01 есть баг, из-за которого это не работает. Обойти его никак нельзя. В Microsoft Internet Explorer 5.5 также есть этот баг, но его уже можно устранить установкой Service Pack 2 или выше.

Замечание: Если включен безопасный режим, то uid скрипта будет добавляться к realm части WWW-Authenticate заголовка (используется для HTTP-аутентификации).

Замечание:

Спецификация HTTP/1.1 требует указывать абсолютный URI в качестве аргумента » Location:, включающий схему, имя хоста и абсолютный путь, хотя некоторые клиенты способны принимать и относительные URI. Абсолютный URI можно построить самостоятельно с помощью $_SERVER[‘HTTP_HOST’], $_SERVER[‘PHP_SELF’] и dirname():

Замечание:

Идентификатор сессии не будет передаваться вместе с заголовком Location, даже если включена настройка session.use_trans_sid. Его нужно передавать вручную, используя константу SID.

doc.php.sh

After lots of research and testing, I'd like to share my findings about my problems with Internet Explorer and file downloads.

  Take a look at this code, which replicates the normal download of a Javascript:

<?php
if(strstr($_SERVER["HTTP_USER_AGENT"],"MSIE")==false) {
 
header("Content-type: text/javascript");
 
header("Content-Disposition: inline; filename="download.js"");
 
header("Content-Length: ".filesize("my-file.js"));
} else {
 
header("Content-type: application/force-download");
 
header("Content-Disposition: attachment; filename="download.js"");
 
header("Content-Length: ".filesize("my-file.js"));
}
header("Expires: Fri, 01 Jan 2010 05:00:00 GMT");
if(
strstr($_SERVER["HTTP_USER_AGENT"],"MSIE")==false) {
 
header("Cache-Control: no-cache");
 
header("Pragma: no-cache");
}
include(
"my-file.js");
?>

Now let me explain:

  I start out by checking for IE, then if not IE, I set Content-type (case-sensitive) to JS and set Content-Disposition (every header is case-sensitive from now on) to inline, because most browsers outside of IE like to display JS inline. (User may change settings). The Content-Length header is required by some browsers to activate download box. Then, if it is IE, the "application/force-download" Content-type is sometimes required to show the download box. Use this if you don't want your PDF to display in the browser (in IE). I use it here to make sure the box opens. Anyway, I set the Content-Disposition to attachment because I already know that the box will appear. Then I have the Content-Length again.

  Now, here's my big point. I have the Cache-Control and Pragma headers sent only if not IE. THESE HEADERS WILL PREVENT DOWNLOAD ON IE!!! Only use the Expires header, after all, it will require the file to be downloaded again the next time. This is not a bug! IE stores downloads in the Temporary Internet Files folder until the download is complete. I know this because once I downloaded a huge file to My Documents, but the Download Dialog box put it in the Temp folder and moved it at the end. Just think about it. If IE requires the file to be downloaded to the Temp folder, setting the Cache-Control and Pragma headers will cause an error!

I hope this saves someone some time!
~Cody G.

php.net

Содержание headera

Рассмотрим содержимое заголовка для этого сайта:

<!DOCTYPE html>  <html <?php language_attributes(); ?>>  <head>  <meta http-equiv=Content-Type content="text/html;charset=UTF-8">  <meta name="viewport" content="width=device-width" />  <title><?php wp_title( '|', true, 'right' ); ?></title>  <script src="<?php echo get_template_directory_uri(); ?>/js/html5.js" type="text/javascript"></script>  <?php wp_head(); ?>  <link rel="icon" type="image/ico" href="https://saitoseoteka.ru/wp-content/uploads/2014/03/your-faviconvFTyUyHmGi.ico"/><link rel="shortcut icon" type="image/x-icon" href="https://saitoseoteka.ru/wp-content/uploads/2014/03/your-faviconvFTyUyHmGi.ico"/>  </head>  <body <?php body_class(); ?>>  <div id="page" class="hfeed site">  	<header id="masthead" class="site-header" role="banner">  		<hgroup>  			<h1 class="site-title"><a href="<?php echo esc_url( home_url( '/' ) ); ?>" title="<?php echo esc_attr( get_bloginfo( 'name', 'display' ) ); ?>" rel="home"><?php bloginfo( 'name' ); ?></a></h1>  			<h2 class="site-description"><?php bloginfo( 'description' ); ?></h2>  		</hgroup>  <?php if ( get_header_image() ) : ?>  		<a href="<?php echo esc_url( home_url( '/' ) ); ?>"><img src="<?php header_image(); ?>" class="header-image" width="<?php echo get_custom_header()->width; ?>" height="<?php echo get_custom_header()->height; ?>" alt="" /></a>  		<?php endif; ?>    	</header>  	<div id="main" class="wrapper">

Первая строчка — указываем тип документа, далее намного интересней:

  1. <html <?php language_attributes(); ?>> — содержит вызов функции. Если заменить её на <html lang=»ru-RU»>, то мы уменьшим количество запросов к базе данных на единицу, тем самым улучшив и ускорив работу сайта.
  2. <head> — этот тег служит для хранения других элементов помогающих браузеру в работе с данными. Именно внутри него содержатся мета-тэги.
  3. Остальные строки, содержащие обращения к базе данных можно также заменить.

Ускорение работы блога можно получить, заменив функции вызова на голый html код. Рекомендуется оставить только <title><?php wp_title( ‘|’, true, ‘right’ ); ?></title>, чтобы заголовок менялся динамически. Для всего остального можно сделать так:

  • Открыть свой сайт
  • Нажать правой кнопкой мышки и выбрать «Просмотреть исходный код страницы»
  • Скопировать код с самого начала и до закрывающего тега </head>
  • Вставить скопированный код в файл header.php и сохранить изменения
  • Не забыть оставить содержимое <title>

То есть, в итоге должен получиться примерно такой код файла заголовка:

<!DOCTYPE html>  <html lang="ru-RU">  <head>  <meta http-equiv=Content-Type content="text/html;charset=UTF-8">  <meta name="viewport" content="width=device-width" />  <title><?php wp_title( '|', true, 'right' ); ?></title>  <script src="https://адрес скрипта 1" type="text/javascript"></script>  <link rel="alternate" type="application/rss+xml" title="Заголовок ленты" href="http://адрес ленты" />  <link rel='stylesheet' подключение файлов стилей type='text/css' media='all' />  <script type='text/javascript' src='https://адрес скрипта 2'></script>  <script type='text/javascript' src='https://адрес скрипта 3'></script>  <meta name="generator" content="WordPress 3.9.2" />  <link rel='shortlink' href='http://адрес сайта/' />  	</header>  

Разный заголовок для разных страниц

Это самое интересное. Для создания landing page, или просто для придания уникальности своему сайту, можно сделать для некоторых записей и страниц свой отдельный файл заголовка header.php, то есть сделать уникальную шапку — от кода  до дизайна.

Ярким примером такой замены может быть предыдущая запись о эффекте parallax на сайтах. Чтобы для некоторой записи сделать свой header, нужно выполнить несколько простых действий:

  1. Создать новый файл в папке с шаблоном сайта, который нужно назвать по своим правилам: на первом месте обязательно должно быть слово «header», затем через дефис пишем уникальное название. Допустим, можно назвать так: header-flat.php.
  2. Открываем вновь созданный файл и заполняем нужными тегами, вставляем нужную картинку, сохраняем.
  3. Теперь, в функцию вызова шапки сайта get_header(), в скобки вписываем название flat, то есть вызов будет выглядеть так: get_header( flat ).

Для записи: нужно получить уникальный ID записи, затем создать там же, где создавали новый файл шапки, файл с включением в название этого ID. Допустим ID записи — 2344, тогда файл нужно назвать single-2344.php (single.php — файл одиночной записи сайта на Вордпресс).

Для страницы — аналогично предыдущему пункту, только название будет page-2345.php.

Подключение новой шапки для записи:

  • в файл «Одна запись (single.php)» в самом начале вписываем <?php if(is_single(2344)) { include ‘single-2346.php’; } else { ?>, а в конце <?php } ?>.
  • в файле single-2346.php вместо get_header() вписываем get_header( flat ).
  • Готово!

Подключение новой шапки для страницы:

здесь нужно просто открыть файл page-2345.php, вставить в него весь код из файла page.php. Остаётся только заменить get_header() на get_header( flat ).

saitoseoteka.ru


You May Also Like

About the Author: admind

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.