В большинстве приложений у вас, вероятно, будут учетные записи пользователей. И если вы это сделаете, вы, безусловно, захотите ограничить то, к чему имеет доступ конкретный пользователь. JSON Web Tokens — это популярный метод авторизации пользователей на ресурсах внутри вашего приложения на стороне клиента.

Когда вы отправляете обычный запрос на выборку серверу, вы обычно отправляете method запроса (GET, POST и т. д.) вместе с объектом header. Что-то типа:

Это прекрасно работает, но в этом запросе недостаточно информации для авторизации пользователя после того, как запрос попадет на серверную часть. Дополнительная информация, которая нам нужна, — это веб-токен JSON. Как только пользователь войдет в приложение, все последующие запросы будут отправляться вместе с уникальным токеном, который предоставляет пользователю доступ к любым маршрутам и ресурсам, разрешенным с помощью этого токена.

Маркер должен быть отправлен как другая пара ключ/значение объекта headers. key будет «Авторизация», а value будет «Носитель token», например:

Этот запрос попадет на соответствующий контроллер в вашем бэкенде Rails. В этом контроллере у вас будет несколько методов, которые представляют actions для вашего routes. Обычный способ разрешить доступ к этим методам/действиям — использовать макрос before_action, который Rails предоставляет в верхней части класса вашего контроллера.

Выше мы выполняем метод require_login перед запуском любого действия в файле ConversationsController. Откуда require_login и authorize? Хорошо видно сверху, что ConversationsController наследуется от ApplicationController. Итак, ApplicationController — это место, где живут эти два метода. А поскольку ApplicationController наследуется от ActionController, любой метод в ApplicationController будет доступен во всех других наших контроллерах.

В конечном счете, наш запрос направляется к действию index внутри ConversationsController:

Ниже показано, как выглядит ApplicationController. Здесь мы рассмотрим весь код, чтобы увидеть, что происходит по мере выполнения нашего запроса.

Итак, вспомним, что методы require_login и authorize выполняются первыми, когда мы вызываем их с помощью макроса before_action. Метод require_login отобразит объект ошибки JSON, если пользователь НЕ вошел в систему. Метод authorize отобразит объект ошибки JSON, если вошедший в систему пользователь НЕ является пользователем, идентификатор пользователя которого передан в URL-адресе. Это означает, что действие index фактически не будет выполнено, если существует какой-либо из этих объектов ошибки, поэтому авторизация работает. Но как?

Как мы узнаем, вошел ли пользователь в систему? Мы видим, что ApplicationController имеет метод logged_in?, который возвращает оператор двойного удара для метода current_user. Таким образом, пользователь считается вошедшим в систему, если метод logged_in? возвращает значение true, а это означает, что метод current_user должен вернуть фактический объект (пользователя), чтобы оператор двойного удара выдал true.

Чтобы метод current_user возвращал объект (пользователя), метод decode_token должен возвращать значение true. В методе decode_token действительно происходит волшебство. Токен, который мы отправили в нашем запросе на выборку с «Авторизацией» headers, декодируется здесь с помощью «JWT.decode» с переданным нашим токеном. Из декодированного результата мы извлекаем идентификатор пользователя внутри метода current_user. Затем мы используем метод find_by Active Record, чтобы найти пользователя с этим идентификатором пользователя. Оттуда мы можем не только проверить, вошел ли пользователь в систему, но и убедиться, что пользователь авторизован для просмотра этого контента.

Что хорошего в макросе before_action Rails, так это то, что мы можем ограничить любое из наших действий/контроллеров одной строкой кода. Я могу так же легко использовать метод require_login в моем UsersController:

У вас может возникнуть вопрос: откуда на самом деле token во внешнем интерфейсе при отправке запроса? Я использовал вариант localStorage, который может быть или не быть лучшим способом. Вы можете сохранить токен в localStorage со следующей строкой в ​​ответе об успешном входе в систему: localStorage.setItem(‘token’, jwt)

Вот и все!

https://www.dougschallmoser.com/