Невозможно игнорировать mod переписать внутренние перенаправления с флагом NS
я определил пару mod_rewrite
правила .htaccess
файл, один, чтобы переписать путь URL из /rwtest/source.html
до /rwtest/target.html
, а другой запретить прямой доступ к /rwtest/target.html
. То есть, все пользователи, желающие увидеть содержимое /rwtest/target.html
введите /rwtest/source.html
в их строке URL.
я пытался использовать NS
флаг в правиле forbid для предотвращения перезаписи URL-адресов также запрещен, но, похоже, этот флаг не различает первый запрос и внутренний перенаправлять. Казалось бы, что NS
должен делать свою работу, но я уверен, что я что-то неправильно понял.
может кто-нибудь прояснить это поведение? Что именно делает это внутреннее перенаправление не внутренним подреберьем, что NS
флаг может игнорировать?
детали:
вот мой полный :
Options +FollowSymLinks -Multiviews
RewriteEngine on
RewriteBase /rwtest
# Forbid rule. Prohibit direct access to target.html. Note the NS flag.
RewriteRule ^target.html$ - [F,NS]
# Rewrite rule. Rewrite source.html to target.html.
RewriteRule ^source.html$ target.html
я запускаю Apache 2.4.9 в Windows 7 x64, но я наблюдал подобное поведение на Apache 2.4.3 в Linux. Вот вывод журнала для запрос /rwtest/source.html
.
[rewrite:trace3] [rid#20b6200/initial] [perdir C:/Apache24/htdocs/rwtest/] strip per-dir prefix: C:/Apache24/htdocs/rwtest/source.html -> source.html
[rewrite:trace3] [rid#20b6200/initial] [perdir C:/Apache24/htdocs/rwtest/] applying pattern '^target.html$' to uri 'source.html'
[rewrite:trace3] [rid#20b6200/initial] [perdir C:/Apache24/htdocs/rwtest/] strip per-dir prefix: C:/Apache24/htdocs/rwtest/source.html -> source.html
[rewrite:trace3] [rid#20b6200/initial] [perdir C:/Apache24/htdocs/rwtest/] applying pattern '^source.html$' to uri 'source.html'
[rewrite:trace2] [rid#20b6200/initial] [perdir C:/Apache24/htdocs/rwtest/] rewrite 'source.html' -> 'target.html'
[rewrite:trace3] [rid#20b6200/initial] [perdir C:/Apache24/htdocs/rwtest/] add per-dir prefix: target.html -> C:/Apache24/htdocs/rwtest/target.html
[rewrite:trace2] [rid#20b6200/initial] [perdir C:/Apache24/htdocs/rwtest/] trying to replace prefix C:/Apache24/htdocs/rwtest/ with /rwtest
[rewrite:trace5] [rid#20b6200/initial] strip matching prefix: C:/Apache24/htdocs/rwtest/target.html -> target.html
[rewrite:trace4] [rid#20b6200/initial] add subst prefix: target.html -> /rwtest/target.html
[rewrite:trace1] [rid#20b6200/initial] [perdir C:/Apache24/htdocs/rwtest/] internal redirect with /rwtest/target.html [INTERNAL REDIRECT]
[rewrite:trace3] [rid#20ba360/initial/redir#1] [perdir C:/Apache24/htdocs/rwtest/] strip per-dir prefix: C:/Apache24/htdocs/rwtest/target.html -> target.html
[rewrite:trace3] [rid#20ba360/initial/redir#1] [perdir C:/Apache24/htdocs/rwtest/] applying pattern '^target.html$' to uri 'target.html'
[rewrite:trace2] [rid#20ba360/initial/redir#1] [perdir C:/Apache24/htdocs/rwtest/] forcing responsecode 403 for C:/Apache24/htdocs/rwtest/target.html
решения
я опубликовал несколько обходных путей ниже.
1 ответов
есть несколько обходных путей для этого, каждый со своими плюсами и минусами. Как отказ от ответственности, я только протестировал их в .htaccess
контексте.
Способ 1. Проверьте наличие пустого REDIRECT_STATUS
добавить RewriteCond
проверка, чтобы увидеть, если %{ENV:REDIRECT_STATUS}
пусто. Если он пуст, то текущий запрос не является внутренним перенаправлением.
плюсы
- самый простой способ определить внутренний перенаправлять.
минусы
-
отсутствие документации. На странице Пользовательские Ответы На Ошибки кратко упоминает эту переменную:
REDIRECT_
переменные среды создаются из переменных среды, которые существовали до перенаправления. Они переименованы сREDIRECT_
префикс, т. е.HTTP_USER_AGENT
становитсяREDIRECT_HTTP_USER_AGENT
.REDIRECT_URL
,REDIRECT_STATUS
иREDIRECT_QUERY_STRING
гарантированы, что будут установлены, и другие заголовки будут только если они существовали до возникновения ошибки.я пробовал все другие
REDIRECT_
переменнаяRewriteCond
, но все они, кромеREDIRECT_STATUS
были пусты для внутренних редиректов. Почему?--12--> особенный вmod_rewrite
остается загадкой.
пример
# Forbid rule. Prohibit direct access to target.html.
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^target.html$ - [F]
# Rewrite rule. Rewrite source.html to target.html.
RewriteRule ^source.html$ target.html
кредиты для этого подхода перейти к URL переписать: внутренняя ошибка сервера.
Способ 2. Правило остановки перезаписи обработка с конца
в отличие от L
флаг END
останавливает переписывать правила даже для внутренних перенаправлений.
плюсы
- простой. Просто дополнительный флаг.
минусы
- не дает вам достаточно контроля над тем, какие правила обрабатывать и какие пропускать.
пример
# Forbid rule. Prohibit direct access to target.html.
RewriteRule ^target.html$ - [F]
# Rewrite rule. Rewrite source.html to target.html.
RewriteRule ^source.html$ target.html [END]
для получения дополнительной информации см. конец флаг.
Способ 3. Сопоставьте с исходным URL-адресом в THE_REQUEST
%{THE_REQUEST}
полная строка HTTP-запроса, отправленная браузером на сервер (например, " GET / index.html HTTP / 1.1").
THE_REQUEST
не изменяется с внутренними перенаправлениями, поэтому вы можете сопоставить его.
плюсы
- может использоваться для сопоставления с исходным URL-адресом даже во втором раунде Обработка URL-адрес.
минусы
значительно сложнее, чем другие подходы. Заставляет использовать
RewriteCond
где только одинRewriteRule
было бы достаточно.соответствует полному URL-адресу, который не был unescaped (декодирован), в отличие от большинства других переменных.
неудобно использовать в несколько
RewriteRule
s.RewriteCond
s можно скопировать над каждымRewriteRule
или значение можно экспортировать в переменную среды (см. Пример). Обе хакерские альтернативы.
пример
# Forbid rule. Prohibit direct access to target.html.
RewriteCond %{THE_REQUEST} "^[^ ]+ ([^ ?]*)" # extract path from request line
RewriteCond %1 ^/rwtest/target.html$
RewriteRule ^ - [F]
# Rewrite rule. Rewrite source.html to target.html.
RewriteRule ^source.html$ target.html
или экспортируйте путь к переменной среды и используйте его в нескольких RewriteRule
s.
# Extract the original URL and save it to ORIG_URL.
RewriteCond %{THE_REQUEST} "^[^ ]+ ([^ ?]*)" # extract path from request line
RewriteRule ^ - [E=ORIG_URL:%1]
# Forbid rule. Prohibit direct access to target.html.
RewriteCond %{ENV:ORIG_URL} ^/rwtest/target.html$
RewriteRule ^ - [F]
# Rewrite rule. Rewrite source.html to target.html.
RewriteCond %{ENV:ORIG_URL} ^/rwtest/source.html$
RewriteRule ^ target.html