Лак и 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 всегда будут передаваться бэкэнду с заголовком авторизации клиента.