Вопрос или проблема
У меня возникла проблема с несколькими запросами к серверу, которые вызывают у меня недоумение. Ситуация такова, что некоторые из моих форм отправляются на сервер по методу POST без проблем, но другие перенаправляются с HTTPS на HTTP, по тому же URL, но как GET-запросы. Поэтому, когда мой скрипт получает запрос, данных POST нет.
Я проверил свой .htaccess, и он выглядит нормально, но я также не вижу, почему это могло бы привести к такой ситуации (признаюсь, я не суперзвезда Apache).
Я добавил отладчик, чтобы остановиться на первой строке кода в моем приложении, и запрос в этот момент уже изменён, что и привело меня сюда.
На первом изображении показан защищенный POST запрос, отправленный со страницы
На втором изображении показан незащищенный редирект как GET запрос
А мой .htaccess
выглядит так
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
# Перенаправить все HTTP запросы на HTTPS
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Обеспечить правильную обработку index.php, site.php и cp.php
RewriteRule ^(index|site|cp)\.php$ - [L]
RewriteRule ^(css|js|img)/ - [L]
RewriteRule ^favicon.ico$ - [L]
# Перенаправить все остальные запросы на соответствующий PHP файл
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php [NC,L,QSA]
</IfModule>
Как видите, у меня есть 3 точки входа в приложение index.php
для запросов гостей, site.php
для аутентифицированных пользователей и cp.php
для администраторов (панель управления). Они помогают с маршрутизацией и очень похожи (запускают систему, аутентификация, обработка запроса).
Форма, которую я переписываю прямо сейчас, является второй формой, с которой это происходит, и, помимо атрибута action, они выглядят одинаково. Я пробовал с и без enctype, пробовал разные браузеры и перезагружал и перестраивал контейнер docker, чтобы выяснить причину этой проблемы.
Кроме созданного мной фреймворка, здесь используется обычный PHP, но как я думаю, мы видим, что это не проблема кода.
Хорошо, так что во время выполнения некоторых непродолжительных отладок мой IDE показал диалог, потому что не смог найти правильный путь в моем локальном коде для того, что на сервере. Я подумал, что это очень странно, потому что я работал в этой области весь день… ну, не совсем. Я нажал на ссылку в меню для страницы, над которой работал, а эта чертова ссылка не имела схемы запроса, это была просто относительная ссылка. Поэтому сервер вернул страницу по HTTP (без S), и вот, по сути, была проблема.
Я всегда предполагал, что если нажать на относительную ссылку на странице, обслуживаемой по HTTPS, эта страница будет возвращена по HTTPS… но здесь это не так. Поскольку это то, что я всегда предполагал на протяжении 20 лет, я был бы очень удивлен, если бы я ошибался, так что может быть другая проблема, вызывающая это.
По крайней мере, теперь я знаю, почему в этом случае это происходит.
Спасибо за комментарии.
Ответ или решение
Ваша проблема с перенаправлением запросов с HTTPS на HTTP, а также потерей данных POST вызвана использованием относительных ссылок на вашей странице. Давайте разберёмся с ситуацией и возможными решениями.
Объяснение проблемы
Когда вы делаете POST-запрос из формы на страницу с HTTPS, браузер отправляет этот запрос на указанный вами URL. Однако, если у вас в коде используется относительная ссылка (например, <form action="/submit">
), браузер может интерпретировать её по-разному в зависимости от текущего протокола. То есть, если пользователь находится на странице с HTTPS и отправляет форму с относительным действием, браузер может отправить данные на сервер по HTTP, если относительная ссылка не содержит явного указания на протокол (например, https://
).
Рекомендации по решению проблемы
-
Использование абсолютных URL: Вместо относительных ссылок для вашего формы используйте абсолютные URL, начиная с протокола. Например:
<form action="https://yourdomain.com/submit" method="POST">
Это гарантирует, что браузер всегда отправляет запрос через правильный протокол.
-
Настройка .htaccess: Убедитесь, что конфигурация в вашем файле
.htaccess
корректно обрабатывает все запросы и перенаправляет их с HTTP на HTTPS. Вы уже используете следующее правило:RewriteCond %{HTTPS} off RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Это правило должно работать корректно и перенаправлять все HTTP-запросы на HTTPS. Проблема может возникнуть, если пользователь попадает на страницу с HTTP через относительную ссылку, как обсуждалось выше.
-
Проверка всех ссылок: Пройдите через весь ваш код и убедитесь, что все ссылки (не только в формах, но и в навигации, кнопках и т. д.) указывают на HTTPS-ссылки. Это предотвратит возможность перехода на HTTP-страницы при нажатии на относительно прописанные ссылки.
-
Использование HSTS: Рассмотрите возможность включения HSTS (HTTP Strict Transport Security) на вашем сервере. Это может помочь принудительно перенаправлять все запросы на HTTPS. Для этого добавьте в файл конфигурации сервера (например, в
.htaccess
) следующую строку:Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
-
Тестирование: Проверьте работу после внесения изменений. Убедитесь, что все формы и ссылки работают как ожидается, и запросы не перенаправляются обратно на HTTP.
Эти шаги должны помочь вам установить и поддерживать корректное управление протоколами на вашем сайте. Если проблемы всё равно будут возникать, возможно, стоит более детально посмотреть на ваши настройки сервера или другие части кода, которые могут влиять на поведение форм и ссылок.