Добро пожаловать в мир безопасности, где все по-другому.
Topi c более сложный, чем может показаться на первый взгляд. Как уже упоминалось, первый шаг - защитить токен от перехвата с помощью безопасного соединения. Но это не конец истории.
Если токен безопасно передается клиенту, токен должен храниться где-то на клиенте. Существует три основных варианта:
- Хранить токен в кэше сеанса, например, в локальном хранилище.
- Отправить токен как HTTP only cook ie, чтобы к нему нельзя было получить доступ скриптами
- Храните токен где-нибудь во внешнем коде
У каждого подхода есть свои плюсы и минусы. Начнем с локального хранилища.
По сути, локальное хранилище - это большой JavaScript объект, доступный для скриптов. Другими словами: если скрипт может проникнуть на вашу веб-страницу, он сможет прочитать ваше локальное хранилище и, таким образом, может украсть ваш токен.
Затем отправьте токен как HTTP only cook ie. Кажется, этого достаточно. Если это файлы cookie только для HTTP, сценарии не могут получить доступ к информации, поэтому информация в безопасности, верно? Нет. Если сценарий может проникнуть на ваш сайт и с этого сайта делает запрос к защищенному ресурсу, маркер автоматически отправляется браузером (так работают только файлы cookie HTTP). Это известно как Cross-Site-Request-Forgery .
Наконец, можно было просто сохранить токен в скрипте. Это кажется достаточно хорошим, учитывая, что можно выбрать любое возможное имя переменной для токена, и, таким образом, злоумышленнику трудно угадать. Это верно, если кто-то пишет свой собственный код для этой части. Но в большинстве случаев люди будут прибегать к существующим решениям, и злоумышленники могут найти соответствующую переменную и просто прочитать ее значение. Кроме того, если токен не хранится постоянно, это означает, что пользователь должен повторно входить в систему каждый раз, когда браузер закрывается и снова открывается. В зависимости от желаемого UX это может быть не вариант.
Так что «идеального решения» этой проблемы не существует. Это ситуация «выбери свой яд». Но на этом история не заканчивается. Как уже упоминалось, у токенов обычно есть срок годности. Однако с точки зрения пользователя плохо, если пользователь должен повторно входить в систему каждый час или около того, даже если он / она был активен в этот период времени. Если взять, например, стандарт OAUTH 2.0 , у нас будет концепция токена refre sh. Токен refre sh - это специальный токен, который, если предоставляется, генерирует новый токен доступа JWT. В этом случае токен доступа может иметь очень короткий срок действия (например, 5 минут). Если срок действия токена доступа истекает, клиент может запросить новый токен, используя токен refre sh, который обычно является долгоживущим, возможно, вообще не истекает. Но это только решает проблему: теперь токен доступа недолговечен, но если злоумышленник может получить токен refre sh, он / она имеет возможность продолжать выпускать новые токены доступа. Но можно сохранить состояние токена refre sh в провайдере аутентификации, например, keycloak имеет функцию аннулирования всех токенов пользователя. Тогда возникает вопрос: как можно уведомить систему о том, что токен был украден, и что все токены должны быть признаны недействительными? Или даже более фундаментально: как вообще можно заметить, что токен refre sh был украден?
Суть в том, что серебряной пули нет. Вам следует посмотреть на свой вариант использования и принять соответствующее решение. Есть лучшие практики, но они могут измениться. И в зависимости от практики внедрение новой передовой практики может занять много времени и / или дорого.