Я пишу веб-приложение на Angular, где аутентификация обрабатывается токеном JWT, что означает, что каждый запрос имеет заголовок «Authentication» со всей необходимой информацией.
Это хорошо работает для вызовов REST, но я не понимаю, как мне обрабатывать ссылки для загрузки файлов, размещенных на бэкэнде (файлы находятся на том же сервере, где размещены веб-службы).
Я не могу использовать обычные <a href='...'/>
ссылки, так как они не будут содержать заголовков и аутентификация не удастся. То же самое для различных заклинаний window.open(...)
.
Некоторые решения, о которых я подумал:
- Создать временную незащищенную ссылку для скачивания на сервере
- Передайте информацию для аутентификации в качестве параметра URL-адреса и обработайте случай вручную.
- Получите данные через XHR и сохраните файл на стороне клиента.
Все вышеперечисленное менее чем удовлетворительно.
1 - это решение, которое я использую прямо сейчас. Мне это не нравится по двум причинам: во-первых, он не идеален с точки зрения безопасности, во-вторых, он работает, но требует довольно много работы, особенно на сервере: чтобы загрузить что-то, мне нужно вызвать службу, которая генерирует новый случайный "url, хранит его где-то (возможно, в БД) в течение некоторого времени и возвращает клиенту. Клиент получает URL-адрес и использует с ним window.open или аналогичный. По запросу новый URL-адрес должен проверить, действителен ли он, а затем вернуть данные.
2 вроде как минимум столько же работы.
3 кажется много работы, даже с использованием доступных библиотек, и много потенциальных проблем. (Мне нужно было бы предоставить свою собственную строку состояния загрузки, загрузить весь файл в память, а затем попросить пользователя сохранить файл локально).
Однако задача кажется довольно простой, поэтому мне интересно, есть ли что-нибудь более простое, что я могу использовать.
Я не обязательно ищу решение "углового" пути. Обычный Javascript подойдет.
источник
Ответы:
Вот способ загрузить его на клиент, используя атрибут загрузки , API выборки и URL.createObjectURL . Вы должны получить файл с помощью JWT, преобразовать полезную нагрузку в большой двоичный объект, поместить этот большой двоичный объект в объектный URL, установить источник тега привязки на этот объектный URL и щелкнуть этот объектный URL в javascript.
Значение
download
атрибута будет конечным именем файла. При желании вы можете извлечь предполагаемое имя файла из заголовка ответа с размещением содержимого, как описано в других ответах .источник
Техника
Основываясь на этом совете Матиаса Волоски из Auth0, известного евангелиста JWT, я решил эту проблему, сгенерировав подписанный запрос с помощью Hawk .
Цитата Волоски:
Здесь у вас есть пример этой техники, используемой для ссылок активации.
бэкенд
Я создал API для подписи моих URL-адресов для скачивания:
Запрос:
Отклик:
С подписанным URL-адресом мы можем получить файл
Запрос:
Отклик:
интерфейс (от jojoyuji )
Таким образом, вы можете сделать все это одним щелчком мыши:
источник
Альтернативой уже упомянутым существующим подходам «fetch / createObjectURL» и «download-token» является стандартная форма POST, предназначенная для нового окна . Как только браузер прочитает заголовок вложения в ответе сервера, он закроет новую вкладку и начнет загрузку. Этот же подход также хорошо работает для отображения ресурса, такого как PDF, в новой вкладке.
Это лучше поддерживает старые браузеры и позволяет избежать необходимости управлять новым типом токена. Это также будет иметь лучшую долгосрочную поддержку, чем базовая аутентификация по URL-адресу, поскольку поддержка имени пользователя и пароля в URL-адресе удаляется браузерами .
На стороне клиента мы используем,
target="_blank"
чтобы избежать навигации даже в случаях сбоя, что особенно важно для SPA (одностраничных приложений).Основное предостережение заключается в том, что проверка JWT на стороне сервера должна получать токен из данных POST, а не из заголовка . Если ваша платформа автоматически управляет доступом к обработчикам маршрутов с помощью заголовка Authentication, вам может потребоваться пометить обработчик как неаутентифицированный / анонимный, чтобы вы могли вручную проверить JWT для обеспечения надлежащей авторизации.
Форма может быть динамически создана и немедленно уничтожена, чтобы она была должным образом очищена (примечание: это можно сделать на простом JS, но здесь для ясности используется JQuery) -
Просто добавьте любые дополнительные данные, которые нужно отправить в качестве скрытых входных данных, и убедитесь, что они добавлены в форму.
источник
Я бы сгенерировал токены для загрузки.
В angular сделайте аутентифицированный запрос для получения временного токена (скажем, на час), затем добавьте его в URL-адрес в качестве параметра получения. Таким образом, вы можете скачивать файлы любым удобным для вас способом (window.open ...)
источник
Дополнительное решение: использование базовой аутентификации. Хотя для этого потребуется немного поработать с серверной частью, токены не будут отображаться в журналах, и не потребуется подписывать URL.
Сторона клиента
Примером URL может быть:
http://jwt:<user jwt token>@some.url/file/35/download
Пример с фиктивным токеном:
http://jwt:eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIwIiwibmFtZSI6IiIsImlhdCI6MH0.KsKmQOZM-jcy4l_7NFsv1lWfpH8ofniVCv75ZRQrWno@some.url/file/35/download
Затем вы можете вставить это
<a href="...">
илиwindow.open("...")
- все остальное сделает браузер.Сторона сервера
Реализация здесь зависит от вас и зависит от настроек вашего сервера - она не слишком сильно отличается от использования
?token=
параметра запроса.Используя Laravel, я пошел простым путем и преобразовал базовый пароль аутентификации в
Authorization: Bearer <...>
заголовок JWT , позволяя обычному промежуточному программному обеспечению аутентификации обрабатывать все остальное:источник