Разница между HTTP и HTTPS
В связи с массовым переходом сайтов на HTTPS перед разработчиками и администраторами сайтов встал ряд новых проблем. Одной из них является редирект с HTTP на HTTPS и необходимость правильно обрабатывать переадресацию на канонический адрес сайта, чтобы избежать дублирования контента.
HTTPS и редиректы
Рассмотрим пример. Допустим, что у нас есть сайт dnsimple.com . Его канонический URL-адрес — https://dnsimple.com . Тем не менее, существует четыре различных способа, с помощью которых можно подключиться к сайту, и нужно обеспечить, чтобы при любом из них пользователь перенаправлялся на https://dnsimple.com :
Исходный способ | Тип |
http://dnsimple.com | HTTP + no-www |
https://dnsimple.com | HTTPS + no-www |
http://www.dnsimple.com | HTTP + www |
https://www.dnsimple.com | HTTPS + www |
Настройка htaccess редиректов HTTP на HTTPS часто является причиной путаницы. Не всегда понятно, как правильно обрабатывать через HTTPS редиректы с WWW на не-WWW (или наоборот ), и почему для этого нужен сертификат SSL / TLS . Чтобы правильно настроить эти перенаправления, необходимо понять основные принципы обработки запросов HTTPS .
Далее мы рассмотрим, в каком порядке устанавливается соединение по протоколу HTTPS , как происходит обработка HTTP-запросов и настройка редиректов с поддержкой HTTPS .
Поток запроса HTTPS
На приведенном выше изображении показана схема прохождения запросов / ответов HTTPS . Для простоты мы разбили все действия на три фазы:
- На первом этапе клиент и сервер договариваются о деталях шифрования, таких как протокол шифрования и набор шифров. Также происходит обмен информацией, необходимой для переключения на защищенное соединение: открытые ключи, сведения о сертификате и т.д. Эта фаза называется «SSL / TLS рукопожатие »;
- На втором этапе клиент готовит HTTP-запрос , шифрует его и отправляет на сервер для обработки. Сервер принимает зашифрованный HTTP-запрос , расшифровывает его, обрабатывает и выдает HTTP response (ответ );
- На третьем этапе, сервер шифрует ответ и отправляет его клиенту для обработки. Клиент получает зашифрованный HTTP response , дешифрует и обрабатывает его (например, браузер начинает загружать и отображать элементы ).
Эта схема потока редиректа с HTTP на HTTPS применима к любому запросу, независимо от содержимого ответа HTTP .
Выше я написал запрос HTTP и ответ HTTP для определенных целей (обратите внимание, что я использовал HTTP , а не HTTPS ). С точки зрения содержимого и структуры важно понимать, что HTTPS-запрос — это HTTP-запрос , но передаваемый через защищенное соединение (TLS / SSL ).
HTTPS-согласования и редиректы
Одна из самых распространенных ошибок при настройке HTTPS-редиректов — это предположение, что вам не нужен сертификат SSL при переадресации клиента с одного домена на другой.
Если посмотреть на поток запросов, то видно, что обмен сертификатами SSL и согласование шифрования выполняются на первом этапе. Обратите внимание, что на этом этапе сервер ничего не знает, какая страница нужна клиенту: клиент и сервер решают, как взаимодействовать друг с другом.
После завершения первого этапа, когда клиент и сервер нашли общий язык (протокол шифрования ), они могут начать взаимодействовать друг с другом, используя зашифрованное соединение. В этот момент клиент отправляет HTTP-запрос на сервер, а сервер отправляет HTTP-ответ , содержащий редирект.
Не забывайте, что редирект — это HTTP-ответ с кодом 301 (иногда 302 или 307 ):
HTTP/1.1 301 Moved Permanently Server: nginx Date: Mon, 01 Aug 2016 14:41:25 GMT Location: https://dnsimple.com/
Перед тем, как сделать редирект с HTTPS на HTTP , помните, что, если нужно создать редирект для всего домена, то необходим валидный сертификат SSL для перенаправляемого домена. Для согласования шифрования требуется сертификат SSL , и происходит оно до того, как запрос был обработан, а ответ о редиректе возвращен клиенту.
Если бы все происходило иначе, то редирект бы обрабатывался перед проверкой сертификата SSL . Тогда клиент и сервер были бы вынуждены общаться с помощью обычного HTTP-соединения , которое не шифруется.
Если нужно перенаправить клиента с любой страницы домена https://www.example.com на другую, необходим установленный на сервере валидный сертификат SSL , который распространяется на весь домен www.example.com .
Например, чтобы перенаправить клиента с https://www.example.com на https://example.com , необходимо иметь сертификат, который распространяется на оба или два отдельных сертификата (для каждого хоста соответственно ).
Стратегии HTTPS-редиректов
Мы рассмотрели, как обрабатывается редирект с HTTP на HTTPS через htaccess после SSL / TLS согласования. А также выяснили, что для перенаправления клиентов с сайта или страницы на HTTPS нужен валидный сертификат SSL , который охватывает оба домена. Далее я расскажу об общих стратегиях настройки HTTPS-редиректов .
Существует два типа настройки редиректов с HTTPS :
- Редирект на уровне сервера;
- Редирект на уровне приложений.
Термин сервер обозначает любой сервер, который находится перед веб-приложением и обрабатывает входящий HTTP-запрос . Например, front-end сервер, сервер балансировки нагрузки или единичного приложения.
Термин приложение обозначает веб-приложение, которое может быть либо столь же простым, как PHP-скрипт , либо более сложным, таким как серверное Unicorn-приложение интерпретации Ruby on Rails .
Выполнение HTTPS-редиректов на уровне сервера
Выполнение HTTPS-редиректов на уровне сервера является более предпочтительным. В этом случае сервер, на котором установлен сертификат SSL , принимает зашифрованный HTTP-запрос и возвращает зашифрованный HTTP-ответ о редиректе в соответствии с параметрами конфигурации без соединения с сервером приложения или выполнения кода приложения.
Такой подход является более быстрым, так как сервер может обрабатывать редирект без взаимодействия с приложением. В то же время конфигурация серверов менее гибкая по сравнению с тем, что можно сделать с помощью полноценного языка программирования.
htaccess редирект HTTP
на HTTPS
на уровне сервера используется для массового перенаправления. Например, редиректа с WWW
на не-WWW
версию домена с HTTPS
(или наоборот
).
Следующий фрагмент кода является примером конфигурации Nginx , в котором задается редирект с http://example.com , http://www.example.com и https://www.example.com на https://example.com :
server { listen 80; server_name example.com www.example.com; return 301 https://example.com$request_uri; } server { listen 443 ssl; server_name example.com www.example.com; # ssl configuration ssl on; ssl_certificate /path/to/certificate.crt; ssl_certificate_key /path/to/private.key; if ($http_host = www.example.com) { return 301 https://example.com$request_uri; } }
Реализация редиректа на уровне сервера более предпочтительна, но она не всегда осуществима, поскольку вы можете не иметь доступа к конфигурации сервера. Это касается виртуального хостинга или таких платформ, как Heroku , Azure или Google Platform .
Выполнение HTTPS-редиректа на уровне приложений
Когда у вас нет доступа к конфигурации сервера, или логика редиректа является более сложной, необходимо обрабатывать редирект с HTTP на HTTPS на уровне приложений.
Такой подход немного медленнее, потому что сервер должен принять запрос, обработать код приложения (или взаимодействовать с сервером приложений ) и вернуть ответ.
То, как выполняется редирект на уровне приложений, зависит от используемого языка программирования и стека. Вот несколько примеров.
Пакет Goland и net/http
Можно использовать http.Redirect .
Ruby on Rails
Можно настроить редирект на уровне маршрутизатора, использовать промежуточное программное обеспечение Rack или метод redirect_to внутри контроллера:
constraints(host: /www.example.com/) do get "*", to: redirect("https://example.com") end
PHP
Используйте функцию header , чтобы отправить HTTP-заголовок перенаправления:
В некоторых случаях это единственно возможный подход. Например, если нужно перенаправить клиентов с WWW на не-WWW версию домена, с HTTPS на Heroku или Azure (или наоборот ), то придется указать оба домена в одном приложении, установить сертификат и через условия обрабатывать редирект на уровне приложений.
Альтернативные способы выполнения HTTPS-редиректа
Существует несколько альтернативных способов редиректа с HTTP на HTTPS .
В некоторых ситуациях отсутствует доступ к конфигурации сервера, а платформа, на которой размещен сайт, не позволяет использовать язык программирования. В качестве типичного примера можно привести Amazon S3 для размещения статических сайтов. В этом случае нужно выяснить, предоставляет ли платформа параметры HTTPS-редиректов , которые можно настроить.
Другой вариант заключается в использовании автономного, независимого приложения для редиректов. Например, если нужно перенаправить клиентов с https://alpha.com на https://beta.com . Тогда для домена alpha.com в качестве DNS можно указать другой сервис или сервер, на котором размещен beta.com . А также настроить редирект на уровне сервера или установить приложение, которое будет выступать в качестве редиректора. При этом также необходим валидный сертификат для alpha.com , который будет установлен там, где необходимо осуществить редирект.
Иногда возникают ситуации, когда при запросе сайта веб-браузером выдается ошибка. Такие ошибки имеют цифровой код и определенное описание.
(101-199) Информационные ответы
Такие ответы указывают на то, что запрос того или иного клиента принят и происходит его непосредственная обработка.
- 100 - Continue - принята первая часть запрос, клиент может продолжить его передачу.
- 101 - Switching Protocols - сервисом выполняются определенные требования клиента, а также переключаются протоколы, что соответствует данным в поле заголовка Upgrade.
(200-299) Успешные запросы клиента
В данном диапазоне все запросы клиента выполнены успешно.
- 200 - OK - успешная обработка запроса клиента, а в ответе сервера имеются все запрашиваемые данные.
- 201 - Created - такой код состояния может быть использован при смене URL. Помимо кода, сервером также выдается заголовок Location, в котором содержится вся информация о месте перемещения всех новых данных.
- 202 - Accepted - запрос принимается, но его обработка происходит не сразу. Тело содержимого ответа также может содержать определенную информацию о данной транзакции. Не предоставляются никакие гарантии того, что запрос будет удовлетворен, даже если во время приемы он был допустимым.
- 203 - Non-Authoritative Information - в заголовке содержимого имеется информация, которая была получена из локальной копии или от третьей стороны.
- 204 - No Content - в ответе имеется только заголовок и код состояния, само тело ответа не дается. При получении такого ответа документ браузера не должен обновляться. Код может возвращаться обратно после того, как пользователь по пустым участкам изображения.
- 205 - Reset Content - происходит очистка формы, которая используется для дополнительных вводных данных, браузером.
- 206 - Partial Content - сервером возвращается только некоторая часть данных. Используется в ответе на запрос при указании заголовка Range. В заголовке Content-Range сервером должен указываться определенный диапазон, который входит в ответ.
(300-399) Переадресация
Код ответа в таком диапазоне означает, что для удовлетворения запроса клиенту необходимо выполнить определенные действия.
- 300 - Multiple Choices (несколько вариантов на выбор) - затребованный URL может включать несколько ресурсов. В возвращенном сервером теле содержимого должны находиться определенные данные о правильном выборе ресурса.
- 301 - Moved Permanently (ресурс перемещен на постоянной основе) - требуемый URL сервер уже не использует, поэтому и не выполняется операция, которая указана в запросе. В заголовке Location предоставляются данные о новом местонахождении запрашиваемого документа. При последующих запросах необходимо уже указывать новый URL.
- 302 - Moved Temporarily (ресурс временно перемещен) - временное перемещение затребованного URL. В заголовке Location указывается новое месторасположение. После получения кода состояния клиент должен разрешить запрос при помощи нового URL, но в дальнейшем пользоваться только старым.
- 303 - See Other (смотрите другой ресурс) - поиск затребованного URL осуществляется посредством указания другого URL, который находится в заголовке Location.
- 304 - Not Modified (не изменился) - является кодом ответа на заголовок lf-Modified-Since, если не произошло изменение URL. Тело содержимого не присутствует, поэтому клиентом должна использоваться его локальная копия.
- 305 - Use Proxy (используйте прокси-сервер) - обращаться к запрашиваемому ресурсу необходимо посредством прокси-сервера, который указывается в поле Location. Также в этом поле имеется URL необходимого прокси-сервера. Запрос необходимо повторить получателю.
(400-499) Неполные запросы клиента
В данном диапазоне коды ответов означают, что запрос клиента неполный. Также это может означать, что клиенту необходимо ввести дополнительную информацию.
- 400 - Bad Request (некорректный запрос) - сервер не понимает запрос из-за синтаксиса malformed. Запрос можно повторить, но только после проведения определенных модификаций.
- 401 - Unauthorized (нет разрешения) - пользователь должен подтвердить свою подлинность. В ответе должно присутствовать поле заголовка WWW-Authenticate с вызовом, который применяется к запрошенному ресурсу. Запрос может повториться, но уже с подходящим полем заголовка Authorization. Если в данном поле уже имеются рекомендации по установлению подлинности, то код состояния 401 показывает, что такие рекомендации не подходят для установления подлинности.
- 402 - Payment Required (требуется оплата) - код зарезервирован и будет использоваться в будущем, но он еще не реализован в HTTP.
- 403 - Forbidden (доступ запрещен) - отклонение запроса, так у сервера нет возможности ответить клиенту.
- 404 - Not Found (ресурс не найден) - по указанному URL уже не существует необходимого документа, то есть сервер не нашел ничего, что могло бы соответствовать данному запросу.
- 405 - Method Not Allowed (недопустимый метод) - в заголовке Allow отмечается, что применяемый клиентом метод не поддерживается.
- 406 - Not Acceptable (неприемлемый запрос) - идентифицируемый ресурс может генерировать только объекты с характеристикой содержимого, которые не согласуются с заголовками приема.
- 407 - Proxy Authentication Required (необходима регистрация на сервере-представителе) - указывает на необходимость установления подлинности клиента прокси-серверу. Прокси-сервером возвращается поле заголовка Proxy-Authenticate, где содержится определенный вызов. Запрос может быть повторен, но уже при указании подходящего поля заголовка.
- 408 - Request Timeout (время обработки запроса истекло) - запрос не осуществился клиентом за время ожидания сервером. Запрос можно повторить позже.
- 409 - Conflict (конфликт) - запрос не выполняется, так как существует конфликт с состоянием ресурса. Предполагается, что пользователь устранит конфликт и передаст запрос повторно.
- 410 - Gone (ресурса больше нет) - затребованный URL больше не т на сервере.
- 411 - Length Required (необходимо указать длину) - запрос не принимается сервером, так как не определен Content-Length. Запрос можно повторить, указав в поле заголовка Content-Length длину тела сообщения.
- 412 - Precondition Failed (не выполнено предварительное условие) - запрос не обрабатывается сервером, так как объект запроса намного больше, чем он может обработать. При таком раскладе возможно закрытие соединения. Если такое состояние временно, то сервер указывает время в заголовке Retry-After, через которое клиент может повторить попытку.
- 413 - Request Entity Too Large (запрашиваемый элемент слишком велик) - запрос не обрабатывается сервером из-за его огромной величины.
- 414 - Request-URI Too Long (идентификатор ресурса в запросе слишком длинный) - запрос не обрабатывается сервером, так как его URL довольно длинный.
- 415 - Unsupported Media Type (неподдерживаемый тип устройства) - отказ сервера в обслуживании запроса, так как запрошенным ресурсом не поддерживается формат объекта запроса.
(500-599) Ошибки сервера
В данном диапазоне указывается, что запрос, скорее всего, не будет выполнен, так как сервер столкнулся с определенной ошибкой.
- 500 - Internal Server Error (внутренняя ошибка сервера) - во время обработки запроса один из компонентов сервера столкнулся с определенной ошибкой конфигурации.
- 501 - Not Implemented (функция не реализована) - запрос клиента не может быть выполнен, так как для выполнения запроса необходима поддержка некоторых функциональных возможностей. Может выдаваться в случае, когда сервер не может распознать метод запроса.
- 502 - Bad Gateway (дефект шлюза) - сервер при работе в качестве прокси-сервера получил недопустимый ответ в цепочке запросов от следующего сервера.
- 503 - Service Unavailable (служба недоступна) - служба временно недоступна, но через некоторое время доступ может возобновиться. При наличии у сервера определенных данных, он может выдать ответ с заголовком Retry-After.
- 504 - Gateway Timeout (время прохождения через шлюз истекло) - шлюзом или сервером превышен лимит времени.
- 505 - HTTP Version Not Supported (неподдерживаемая версия HTTP) - сервером не поддерживается версия протокола HTTP, которая использовалась в запросе.
HTTP (HyperText Transfer Protocol - протокол передачи гипертекста) был разработан как основа World Wide Web.
Работа по протоколу HTTP происходит следующим образом: программа-клиент устанавливает TCP-соединение с сервером (стандартный номер порта-80) и выдает ему HTTP-запрос. Сервер обрабатывает этот запрос и выдает HTTP-ответ клиенту.
Структура HTTP-запроса
HTTP-запрос состоит из заголовка запроса и тела запроса, разделенных пустой строкой. Тело запроса может отсутствовать.
Заголовок запроса состоит из главной (первой) строки запроса и последующих строк, уточняющих запрос в главной строке. Последующие строки также могут отсутствовать.
Запрос в главной строке состоит из трех частей, разделенных пробелами:
Метод (иначе говоря, команда HTTP):
GET - запрос документа. Наиболее часто употребляемый метод; в HTTP/0.9, говорят, он был единственным.
HEAD - запрос заголовка документа. Отличается от GET тем, что выдается только заголовок запроса с информацией о документе. Сам документ не выдается.
POST - этот метод применяется для передачи данных CGI-скриптам. Сами данные следуют в последующих строках запроса в виде параметров.
PUT - разместить документ на сервере. Насколько я знаю, используется редко. Запрос с этим методом имеет тело, в котором передается сам документ.
Ресурс - это путь к определенному файлу на сервере, который клиент хочет получить (или разместить - для метода PUT). Если ресурс - просто какой-либо файл для считывания, сервер должен по этому запросу выдать его в теле ответа. Если же это путь к какому-либо CGI-скрипту, то сервер запускает скрипт и возвращает результат его выполнения. Кстати, благодаря такой унификации ресурсов для клиента практически безразлично, что он представляет собой на сервере.
Версия протокола -версия протокола HTTP, с которой работает клиентская программа.
Таким образом, простейший HTTP-запрос может выглядеть следующим образом:
Здесь запрашивается корневой файл из корневой директории web-сервера.
Строки после главной строки запроса имеют следующий формат:
Параметр: значениe .
Таким образом задаются параметры запроса. Это является необязательным, все строки после главной строки запроса могут отсутствовать; в этом случае сервер принимает их значение по умолчанию или по результатам предыдущего запроса (при работе в режиме Keep-Alive).
Перечислю некоторые наиболее употребительные параметры HTTP-запроса:
Connection
(соединение)- может принимать значения Keep-Alive и close.
Keep-Alive ("оставить в живых") означает, что после выдачи данного документа
соединение с сервером не разрывается, и можно выдавать еще запросы.
Большинство браузеров работают именно в режиме Keep-Alive, так как он
позволяет за одно соединение с сервером "скачать" html-страницу и рисунки
к ней. Будучи однажды установленным, режим Keep-Alive сохраняется до
первой ошибки или до явного указания в очередном запросе Connection: close.
close ("закрыть") - соединение закрывается после ответа на данный запрос.
User-Agent - значением является "кодовое обозначение" браузера, например:
Mozilla/4.0 (compatible; MSIE 5.0; Windows 95; DigExt)
Accept - список поддерживаемых браузером типов содержимого в порядке их предпочтения данным браузером, например для моего IE5:
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/msword, application/vnd.ms-powerpoint, */*
Это, очевидно, нужно для случая, когда сервер может выдавать один и тот же документ в разных форматах.
Значение этого параметра используется в основном CGI-скриптами для формирования ответа, адаптированного для данного браузера.
Referer - URL, с которого перешли на этот ресурс.
Host - имя хоста, с которого запрашивается ресурс. Полезно, если на сервере имеется несколько виртуальных серверов под одним IP-адресом. В этом случае имя виртуального сервера определяется по этому полю.
Accept-Language - поддерживаемый язык. Имеет значение для сервера, который может выдавать один и тот же документ в разных языковых версиях.
Формат HTTP-ответа
Формат ответа очень похож на формат запроса: он также имеет заголовок и тело, разделенное пустой строкой.
Заголовок также состоит из основной строки и строк параметров, но формат основной строки отличается от таковой в заголовке запроса.
Основная строка запроса состоит из 3-х полей, разделенных пробелами:
Версия протокола - аналогичен соответствующему параметру запроса.
Код ошибки - кодовое обозначение "успешности" выполнения запроса. Код 200 означает "все нормально" (OK).
Словесное описание ошибки - "расшифровка" предыдущего кода. Например для 200 это OK, для 500 - Internal Server Error.
Наиболее употребительные параметры http-ответа:
Connection
- аналогичен соответствующему параметру запроса.
Если сервер не поддерживает Keep-Alive (есть и такие), то значение
Connection в ответе всегда close.
Поэтому, на мой взгляд, правильной тактикой браузера является следующая:
1. выдать в запросе Connection: Keep-Alive;
2. о состоянии соединения судить по полю Connection в ответе.
Content-Type ("тип содержимого") - содержит обозначение типа содержимого ответа.
В зависимости от значения Content-Type браузер воспринимает ответ как HTML-страницу, картинку gif или jpeg, как файл, который надо сохранить на диске, или как что-либо еще и предпринимает соответствующие действия. Значение Content-Type для браузера аналогично значению расширения файла для Windows.
Некоторые типы содержимого:
text/html - текст в формате HTML (веб-страница);
text/plain - простой текст (аналогичен "блокнотовскому");
image/jpeg - картинка в формате JPEG;
image/gif - то же, в формате GIF;
application/octet-stream - поток "октетов" (т.е. просто байт) для записи
на диск.
На самом деле типов содержимого гораздо больше.
Content-Length ("длина содержимого") - длина содержимого ответа в байтах.
Last-Modified ("Модифицирован в последний раз") - дата последнего изменения документа.