Лак и ESI HTTP AUTH

Я очень запутался в этой проблеме, и я не знаю, где может быть проблема, поэтому я надеюсь, что вы могли бы помочь мне.

У меня есть аутентификация HTTP BASIC с помощью symfony, и я пытаюсь найти URL, защищенный этой аутентификацией, с тегом на странице Drupal. Все запросы отправляются в Лак

Я даю имя пользователя и пароль в URL:

<esi:include src="http://admin:adminpass@api.dev:8081/app.php/next"/>

В моем файле конфигурации лака у меня есть только те строки для auth.http:

if (req.http.Authorization) {
  return (pass);
}

Мой бэкэнд для Symfony работает хорошо без http-аутентификации, а http-аутентификация работает хорошо, когда нет Varnish и ESI-тегов.

Если у кого-то есть представление о проблеме, скажите, пожалуйста, даже если это не так =)

1 ответ

Решение

ESI на лаке не работает как iframe или тег ссылки в браузере в том смысле, что он не подключается к тому URL, который вы ему даете. ESI просто запускает новый запрос в лаке и проходит через рабочий процесс (vcl_recv и т. Д.).

Вы ожидаете, что лак будет действовать как http-клиент, анализируя URL-адрес, устанавливая заголовок авторизации, устанавливая заголовок узла равным api.dev:8081 и инициируя новое http-соединение / запрос, которого не будет. В этом случае я предполагаю, что он запускает новый req с req.url, установленным в /app.php/next, который наследует заголовки из запроса на родительский ресурс (содержащий тег esi), или, возможно, просто полностью игнорирует тег esi.

Способ выполнить то, что вы хотите сделать, (в vcl_recv):

if (req.esi_level > 0 && req.url == "/app.php/next") {
     set req.http.Authorization = "BASIC [base64 encoded admin:adminpass]"
     return (pass);
}

и тогда тег ESI должен выглядеть <esi:include src="/app.php/next" />

Если вам нужен запрос ESI для подключения к другому бэкэнд-серверу, вам нужно добавить этот сервер в качестве другого бэкэнда с именем:

backend authorization_needed {
   .host = "api.dev";
   .port = "8081";
}

и в vcl_recv, скажите varnish использовать его для запросов ESI:

if (req.esi_level > 0 && req.url == "/app.php/next") {
   set req.http.Authorization = "BASIC [base64 encoded admin:adminpass]"
   set req.backend = authorization_needed;
   return (pass);
}

Вам также может понадобиться установить req.http.Host в этом блоке if, если сервер отвечает на другой виртуальный хост, отличающийся от "api.dev".

Обновить:

Так как базовая авторизация исходит от клиента, и вы вызываете return (pass), когда присутствует req.http.Authorization, лак не будет обрабатывать эти страницы ESI. Вы должны явно включить esi в vcl_fetch (), которая не вызывается при передаче.

Таким образом, чтобы пройти авторизацию для фрагментов ESI, но не для родительской страницы, измените vcl_rev:

if (req.http.Authorization && req.esi_level == 0) {
    set req.http.X-Esi-Authorization = req.http.Authorization;
    unset req.http.Authorization;
}
else if (req.http.X-Esi-Authorization && req.esi_level > 0 ) {
    set req.http.Authorization = req.http.X-Esi-Authorization;
    return (pass);
}

И добавьте в vcl_fetch:

if (req.http.X-Esi-Authorization) {
    set beresp.do_esi = true;
}

Чистый эффект заключается в том, что родительский ответ кэшируется и будет обрабатывать esi; сами фрагменты esi всегда будут передаваться бэкэнду с заголовком авторизации клиента.

Другие вопросы по тегам