Как Apache объединяет несколько соответствующих разделов Location


35

Я работаю над некоторой базовой конфигурацией apache, но я не совсем понимаю, как apache объединяет различные <Location>разделы, когда несколько из них соответствуют URL-адресу входящих запросов. Документация apache в главе «Как объединяются разделы» немного сбивает с толку, когда дело касается порядка / приоритета нескольких соответствующих разделов одного типа.

Например, представьте следующую конфигурацию apache (игнорируйте, имеет ли смысл фактическое содержимое, меня интересует только порядок применения каждого правила / раздела):

<Location / >
  ProxyPass http://backend.com/
  Order allow,deny
  Satisfy any
</Location>

<Location /sub/foo>
  Order allow,deny
</Location>

<Location /sub >
  Order deny,allow
  Require valid-user
  Satisfy all
</Location>

<Location /doesnt/match >
  ProxyPass !
</Location>

Теперь, если клиент делает запрос /sub/foobar, какая конечная конфигурация будет применена к этому запросу?

Является ли примененная конфигурация эквивалентом:

# All the directives contained in all the matchin Locations in declaration order
ProxyPass http://backend.com/
Order allow,deny
Satisfy any
Order allow,deny
Order deny,allow
Require valid-user
Satisfy all

или, может быть

# same as above, but with longest matching path last
ProxyPass http://backend.com/
Order allow,deny
Satisfy any
Order deny,allow
Require valid-user
Satisfy all
Order allow,deny

или что-то совершенно другое.

Спасибо за вашу помощь, я действительно запутался.

Ответы:


44

Порядок слияния довольно сложен, и его легко обнаружить с помощью исключений ... Документ Apache « Как объединяются разделы »

Согласно этой документации, порядок объединения разделов выполняется путем обработки всех соответствующих записей для каждого типа соответствия в том порядке, в котором они встречаются в файлах конфигурации, а затем перехода к следующему типу (за исключением <Directory >, что трактуется в порядке специфичности пути).

Порядок типов Directory, DirectoryMatch, Filesи , наконец Location. Более поздние совпадения перезаписывают более ранние совпадения. (* ProxyPass и Alias ​​снова обрабатываются по-разному, см. Примечание в конце)

И есть несколько важных исключений из этих правил, которые применяются к использованию ProxyPass и ProxyPass в разделе <Location>. (увидеть ниже)

Итак, из приведенного выше примера запрос http://somehost.com/sub/foobar с помощью следующей конфигурации;

<Location / >
  ProxyPass http://backend.com/
  Order allow,deny
  Satisfy any
</Location>

<Location /sub/foo>
  Order allow,deny
</Location>

<Location /sub >
  Order deny,allow
  Require valid-user
  Satisfy all
</Location>

<Location /doesnt/match >
  ProxyPass !
</Location>

Это будет накапливать следующие директивы ....

  ProxyPass http://backend.com/
  Order allow,deny
  Satisfy any
  Order allow,deny
  Order deny,allow
  Require valid-user
  Satisfy all   

С последующими совпадениями удаляются предыдущие дубликаты, в результате чего;

  ProxyPass http://backend.com/
  Order deny,allow
  Require valid-user
  Satisfy all   

Пояснение -
позднее сопоставления перезаписывают более ранние совпадения, за исключением случаев, <Directory>когда сопоставления обрабатываются в следующем порядке: от самого короткого компонента каталога до самого длинного.

Так, например,
<Directory /var/web/dir>
будут обрабатываться раньше,
<Directory /var/web/dir/subdir>
независимо от того, в каком порядке эти директивы были указаны в конфиге, и выигрывает более конкретное совпадение.

Любая совпадающая Locationдиректива всегда переопределит ранее совпадающую Directoryдирективу.

Основная идея заключается в том , что для запроса , как GET /some/http/request.htmlвнутренне он будет переведен на место в файловой системе с помощью Alias, ScriptAliasили для нормального расположения файла под DocumentRootдля VirtualHost , что оно соответствует.

Таким образом, запрос будет иметь следующие свойства, которые он использует для сопоставления:
Location: /some/http/request.html File: /var/www/html/mysite/some/http/request.html Directory: /var/www/html/mysite/some/http

Apache будет применяться в свою очередь , все Directoryматчи, в порядке каталогов специфичностью, от конфигурации, а затем , в свою очередь применить DirectoryMatch, Filesи , наконец , Locationсовпадает в том порядке , в котором они встречаются.

Так Locationпереопределяет Files, что переопределяет DirectoryMatch, с путями, совпадающими Directoryс самым низким приоритетом. Следовательно, в приведенном выше примере запрос /sub/foobarсоответствует первому 3 местоположению по порядку, следовательно, последний выигрывает для конфликтующих директив.

(Вы правы, что из документов не ясно, как разрешаются некоторые крайние случаи, возможно, что любые allow from *связанные с ними директивы типов будут связаны с ассоциированным Order allow,deny, но я не проверял это. Также, что произойдет, если вы соответствуете, Satisfy Anyно вы предварительно собрал Allow from *...)

Интересная заметка про ProxyPass и Alias

Просто чтобы быть раздражающим, ProxyPass и, Aliasкажется, работает в другом направлении .... ;-) Это в основном поражает первый матч, затем останавливается и использует это!

Ordering ProxyPass Directives

The configured ProxyPass and ProxyPassMatch rules are 
checked in the order of configuration. 
The first rule that matches wins. So
usually you should sort conflicting ProxyPass rules starting with the
longest URLs first. Otherwise later rules for longer URLS will be
hidden by any earlier rule which uses a leading substring of the URL.
Note that there is some relation with worker sharing.

For the same reasons exclusions must come before the general 
ProxyPass directives.

поэтому в основном необходимо указывать директивы Alias ​​и ProxyPass, в первую очередь, наиболее конкретные;

Alias "/foo/bar" "/srv/www/uncommon/bar"
Alias "/foo"     "/srv/www/common/foo"

а также

ProxyPass "/special-area" "http://special.example.com" smax=5 max=10
ProxyPass "/" "balancer://mycluster/" stickysession=JSESSIONID|jsessionid nofailover=On

Однако, как указал @orev. Вы можете иметь директиву ProxyPass в директиве Location, поэтому более конкретный ProxyPass в локации превзойдет любой ранее найденный ProxyPass.


3
Спасибо за пометку предупреждения о заказе директив ProxyPass. Избавил меня от головной боли
Джереми Френч

2
Что касается ProxyPass «работы в другом направлении» , это верно только в том случае, если они находятся за пределами <Location>. Внутри a соблюдаются <Location>правила слияния <Location>, что означает, что вы хотите, чтобы ваши наименее специфичные <Location>директивы предшествовали более конкретным. Это позволяет более конкретным переопределять менее конкретные директивы. Вы можете иметь только один ProxyPassза <Location>.
18:30
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.