Схема перенаправления на https и переход к правилам пути

#apache #.htaccess

#apache #.htaccess

Вопрос:

В нашем .htaccess файле есть несколько правил перезаписи на основе пути. Например, если URI указывает на /foobar/somestring перенаправление на /foo/somestring страницу, но мы также хотим принудительно загрузить ресурс https .

Мы могли бы включить https://%{HTTP_HOST} во все RewriteRule s, сначала адресуя более конкретные URI, но я почти уверен, что в этом не должно быть необходимости.

Я просмотрел документы apache flags, но у меня возникли проблемы с поиском способа указать серверу обратиться к scheme одному из способов и продолжить чтение правил и условий для обращения paths .

Это долгосрочный подход, который у нас есть сейчас:

 <IfModule mod_rewrite.c>
  RewriteEngine on
  RewriteBase /
  RewriteCond %{REQUEST_URI}  ^/foo
  # Long list
  RewriteRule ^foobar/(bat.*)$ https://%{HTTP_HOST}/foo/$1 [L,R=301]
  RewriteRule ^foobar/(bas.*)$ https://%{HTTP_HOST}/foo/$1 [L,R=301]
  # URI not found
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule ^ https://%{HTTP_HOST}/index.php [L]
  # And finally
  RewriteCond %{HTTPS} !=on
  RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R=301,L,NC]
</IfModule>
  

Большое спасибо.

Комментарии:

1. Это сложная задача для Apache. Лично я бы для простоты жестко запрограммировал https и покончил с этим. Также я бы поместил всю логику перенаправления https перед логикой маршрутизации 404, чтобы пользователи не видели index.php прямо в их браузере. Пожалуйста, используйте 302 перенаправления при тестировании такого рода материалов, чтобы вы не получили кэшированные 301-е в вашем браузере и не пропустили подобные вещи. Для достижения этого сначала используйте обычные перезаписи, а затем только перенаправляйте внизу. Флаг пропуска, или получение / настройка переменных ENV, или сравнение текущего URI с REQUEST_URI — все это может быть достигнуто.

2. На самом деле нет реальной необходимости комбинировать эти две вещи. Вы реализуете перенаправление на https протокол самостоятельно. Причина в том, что 1. это должно быть сделано только один раз для любого клиента, независимо от того, сколько запросов они отправляют, и 2. что перезапись выполняется на другом хосте внутри вашего http-сервера.

3. @Ultimater что вы подразумеваете под «жестко запрограммировать https для простоты»?

Ответ №1:

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

  • Примером перенаправления может быть изменение протокола с http:// на https:// или добавление или удаление www поддомена.

  • Примером перезаписи может быть получение пути, подобного /foo-bar-bas и, перед отправкой его на обработку сервером (через ASP, Python, php, ruby on rails, node.js и т.д.), переписывая его как article.aspx?name=foo_bar_bar или что-то подобное.

Вы можете видеть в OP выше, перенаправление с http:// на https:// , когда оно находилось в верхней части блока правил, приводило к короткому замыканию перезаписей под ним из-за следующих двух флагов:

  • R=301 который сообщает браузеру: «этот (A) ресурс переместился, теперь он находится в этом (B) местоположении».
  • L который сообщает Apache «прекратить обработку набора правил».
  • Третий флаг, NC означает игнорировать регистр, и /?(.*) в любом случае не чувствителен к регистру.

Все, что нужно, это:

 <IfModule mod_rewrite.c>
  RewriteEngine on
  RewriteBase /
  RewriteCond %{HTTPS} !=on
  RewriteRule ^/?(.*) https://%{HTTP_HOST}/$1
  RewriteCond %{REQUEST_URI}  ^/foobar
  RewriteRule ^foobar/(bat.*)$ /foo/$1 [L,R=301]
  RewriteRule ^foobar/(bas.*)$ /foo/$1 [L,R=301]
</IfModule>
  

Отчасти сбивает с толку то, что мы используем правило «Перезаписи» для достижения «Перенаправления» (а также перезаписи под ним.) Apache также поддерживает директиву перенаправления вне mod_rewrite модуля. Я не уверен, сработает ли это здесь.

Стоит повторить комментарий @Ultimater выше о том, что при тестировании использование кода состояния 302 найдено в отличие от кода состояния 301 перемещено постоянно с R флагом предотвратит отправку неправильного сообщения веб-сканерам или (потенциально вашим собственным) браузерам.