Тему безопасности во фронтенд-части можно разделить на две цели:
- обеспечение безопасности вашего клиента и его данных
- держать ваших клиентов подальше от вещей, к которым у них не должно быть доступа
Первая часть - это очень обширная тема, которая охватывает такие вещи, как межсайтовый скриптинг (XSS), межсайтовый запрос-подделка (CSRF), CORS и другие темы, связанные с тем, как браузер предотвращает утечку ваших данных злоумышленнику или предотвращает злоумышленник от выполнения действий от вашего имени.
Вторая часть больше связана с тем, «как мне ограничить доступ пользователей к определенным частям моего сайта» - таким вещам, как раздел только для участников, панель администратора и т. Д.
Безопасны ли переменные в браузере?
Ваша первая идея может быть такой: «Я собираюсь создать isAdmin
переменную, установить ее в true
каждый раз, когда администратор аутентифицируется, а затем проверю ее в моем приложении.
Но как только вы реализовали это решение - у вас возникает вопрос: «Что, если пользователь просто откроет инструменты разработчика и изменит его на true
на своей стороне? Как я могу это предотвратить? Должен ли я использовать localStorage
, sessionStorage
или есть что-то более безопасное? »
Нам нужно прояснить одну вещь - все, что вы помещаете в клиентский браузер, может быть легко изменено клиентом. Браузер по умолчанию предоставляет злоумышленнику все необходимые инструменты. Он может открыть инструменты разработчика и изменить все переменные в памяти. Он может манипулировать localStorage
, sessionStorage
, cookies
, а с правильными расширениями - даже состоянием компонентов React. Он также может заменить ответ auth endopint и просто каждый раз давать ответ с помощью {isAdmin: true}
.
Вы можете подумать, что можете использовать какую-либо форму кодирования - либо развернуть свою собственную, либо использовать JWT, который затем можно проверить в браузере на предмет любых изменений. Этот подход также ошибочен, потому что вам нужно будет сообщить браузеру о механизме (ключах), используемом для генерации подписи, иначе злоумышленнику просто нужно будет создать свои собственные ключи, изменить поле isAdmin
в JWT и подписать его. с его ключом - подпись действительна, браузер принимает JWT как законный и верит, что пользователь является администратором.
Как запретить пользователю доступ к закрытым частям моего сайта?
Вы делаете это точно так же, как и предполагали: вы создаете переменную, устанавливаете ее на true
только для администраторов, и после прохождения проверки показываете контент только для администраторов.
"Хорошо, это совсем небезопасно - каждый может перейти на страницу администратора и удалить все!" Вы кричите.
Справедливо, но только если вы плохо реализуете свое приложение. Внешняя часть не должна заботиться о действительности предоставленных учетных данных. Он всегда должен принимать данные как «истинные» и просто отображать все переданные данные.
Это внутренняя задача для выполнения этой проверки!
В вашем интерфейсе может быть кнопка «Удалить базу данных». Вы можете даже попытаться скрыть это с помощью некоторой логики, но злоумышленник может загрузить код JavaScript и искать все конечные точки - он найдет http://example.com/api/database/delete
URL (это только для примера, вы всегда должны использовать нотацию CRUD в любом случае :) ) и вызовите его вручную. Если эта операция завершается удалением вашей базы данных - вам серьезно нужно повысить безопасность вашего приложения.
Аналогичным образом ваше приложение может отображать только содержимое элементов под /members/blogpost/read-up-on-all-the-new-things
- злоумышленник всегда может перейти к нему напрямую. Если он увидит контент, это означает, что ваш API (или другие формы доставки контента) спроектирован неправильно - злоумышленник должен быть немедленно перенаправлен на /sign-up
, или в худшем случае он должен увидеть шаблон сообщения в блоге без каких-либо контент загружен.
Backend - решающий фактор
В обоих случаях, описанных выше, злоумышленник может получить доступ к заблокированному контенту, но не может выполнить операцию, связанную с действием. Все они должны взаимодействовать с серверной частью и содержать механизмы аутентификации (я тот, кем я себя называю) и авторизации (могу ли я выполнить это действие).
Если действие разрешено, выполните его и ответьте правильным кодом HTTP (например, 200), если это не разрешено, ответьте кодом ошибки HTTP, например 401 (не аутентифицирован) или 403 (не авторизован). Ваш интерфейс должен отреагировать на это и либо сообщить пользователю, что он делает что-то, на что у него нет разрешения (показать сообщение об ошибке, перенаправить на экран входа в систему), либо просто корректно завершиться неудачей (отобразить шаблон без содержимого или * ахнуть! * - Published at: <date>undefined</date>
).