Как перенаправить на страницу входа, но только когда браузер переходит на страницу - PullRequest
4 голосов
/ 20 апреля 2020

Я пишу прокладку аутентификации / авторизации перед моим HTTP-сервером, которая обнаружит отсутствие токена авторизации - либо токена Bearer в поле Authorization, либо зашифрованного токена в cook ie - и отказаться от удовлетворения запроса. Эта прокладка будет перехватывать каждый запрос ресурса от исходного сервера (это функция Lambda@Edge в CDN AWS CloudFront, перед контентом stati c S3, для контекста).

В случай, когда был сделан запрос, потому что пользователь перешел на URL, либо введя его в браузере или перейдя по ссылке, я хочу, чтобы ответ вызвал перенаправление на мою страницу аутентификации (которая в конечном итоге вернет пользователя к исходному URL, на этот раз с токеном аутентификации). Это поток OAuth2, в отдельном домене защищенный домен не обрабатывает ввод имени пользователя / пароля.

В случае, когда запрос был сделан браузером, просто загружая ресурс, на который ссылается страница (например, изображение, встроенное в страницу, или Javascript / CSS файлов), я хочу просто отказаться от ответа 401/403, в зависимости от ситуации.

То, с чем я борюсь, это как определить, из заголовки запроса, разница между двумя случаями. Есть ли канонический способ сделать это? Такое ощущение, что заголовок Accept должен быть моим руководством в этом, но мне нужно, чтобы это работало, даже если пользователь ввел URL-адрес ресурса изображения в свой браузер (т.е. я не могу просто перенаправить, только если Accept включает text/html). Или я могу полагаться на наличие */*, чтобы указать, что это запрос на навигацию, который заранее не знает, каким будет Content-Type?

Или это просто плохая практика по какой-то причине Я не вижу, и я должен либо всегда перенаправлять, либо всегда отказываться?

Ответы [ 2 ]

1 голос
/ 04 мая 2020

Нет 100% метода, который отличал бы прямой пользовательский запрос от автоматического запроса браузера, потому что они оба сделаны браузером. Но вы можете использовать несколько методов.

  1. Сначала разделите ваши ресурсы на 2 класса.

    • Один класс - это html страницы (обычно их можно определить по имени ресурса. Например, по расширению . php, .aspx , et c или вообще без расширения). Пользователи во время типичного рабочего процесса обычно запрашивают только html страниц. Эти ресурсы перенаправляют неавторизованные запросы на страницу авторизации.
    • Другим классом являются все другие ресурсы (js, css, изображения и т. Д. c). Они просто отклоняют все неавторизованные запросы с кодом 401/403.
  2. Второй подход - пометить все автоматически загружаемые ресурсы на вашей веб-странице специальной пометкой (например, добавив параметр запроса в URI , как ?auto=1). И тогда все запросы с таким параметром будут считаться автоматами c. Маркировка ресурсов проще всего при генерации страницы на бэкэнде или во внешнем интерфейсе.

  3. Третий подход - расширение для первого. Кроме того, мы используем Referer заголовок HTTP-запроса. Он идентифицирует адрес веб-страницы, которая связана с запрашиваемым ресурсом.

    • Когда пользователь вводит URL-адрес непосредственно в поле адреса браузера Referer заголовок отсутствует в запросе.
    • Когда браузер делает запрос изображения, css, et c Referer содержит URL веб-страницы с этим ресурсом.
    • Когда пользователь перемещается между страницами, он содержит URL предыдущей страницы.

Таким образом, мы можем рассматривать все веб-страницы и изображения с пустым заголовком Referer по запросу. И все ресурсы (кроме веб-страниц) с Referer - как автоматический c запрос.

К сожалению, заголовок Referer не надежен - браузеры иногда не отправляют этот заголовок по некоторым причинам - политика конфиденциальности , причины безопасности , et c. Вы можете попробовать это на свой страх и риск.

0 голосов
/ 06 мая 2020

В отсутствие ответа, который фактически решает проблему, я подумал, что должен ответить тем, на котором я неохотно остановился.

Хотя технически правильно, что отсутствие действительных учетных данных может привести к в ответе 401/403 для ресурса это верно и для навигационной нагрузки. Если вы отвечаете 307 на перенаправление для аутентификации, вы уже подрываете это ожидание.

На практике важно то, что видит конечный пользователь: когда браузер пытается загрузить встроенный ресурс, но получает назад 307, он идет и выбирает страницу формы входа HTML, на которую он был перенаправлен. Поскольку это не ресурс изображения (или что-то еще ожидаемое), а также потому, что он изменил тип содержимого на что-то, что потенциально может быть вредоносным, современные браузеры блокируют его на основе CORB. Я не уверен, что делают старые браузеры, но я сомневаюсь, что они отображают HTML вместо img или любого другого элемента, указанного на странице. Результат net одинаков в обоих случаях - вместо встроенного ресурса пользователь видит неработающую ссылку.

Сравните это с нагрузкой, возникающей в результате действия навигации, когда браузер будет счастливо перенаправить и показать HTML форму входа, как и предполагалось. Это может быть немного затруднительно, если вы вставили страницу, которая будет перенаправлена ​​на другую страницу, но мы уже получили X-Frame-Options: DENY в нашей форме входа в систему из соображений безопасности, чтобы в этом случае она не работала.

Таким образом, в отсутствие хорошего способа сделать это «правильно», вы можете просто выбрать перенаправление во всех случаях, и вы получите конечный результат, который, возможно, в порядке. Было бы гораздо приятнее, если бы сам HTTP имел более изящную интеграцию, например, возможность добавить перенаправление в ответе 401/403 и отправить браузеру «куда-то еще», чтобы получить токен Bearer обратно, но есть причины, по которым я не могу понять, почему это плохая идея.

...