Части
перейти к части...
Нам нужно решить еще несколько вопросов прежде, чем вы сможете приступить к разработке непосредственно приложения.
Защита маршрутов
На данный момент даже неавторизированные пользователи имеют доступ к маршруту /dashboard
. Маршруты Vue можно защитить методом, похожим на то, как это делается с помощью middleware в Laravel.
Первое, что вам нужно знать, это то, что мы можем прикреплять произвольные мета-данные к маршрутам через объект meta
. Мы будем использовать этот объект для того, что пометить маршрут /dashboard
как защищенный. Откройте файл routes.js
и отредактируйте маршрут /dashboard
следующим образом:
{
path: '/dashboard',
component: require('./views/Dashboard.vue'),
meta: { middlewareAuth: true }
}
Затем мы можем применить к маршрутизатору глобальный метод beforeEach()
, который позволяет выполнять любые проверки и действия до того, как маршрут будет загружен - прямо как middleware в Laravel.
Удалите весь код после массива routes
и вставьте на его место вот это:
const router = new VueRouter({
routes
});
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.middlewareAuth)) {
if (!auth.check()) {
next({
path: '/login',
query: { redirect: to.fullPath }
});
return;
}
}
next();
})
export default router;
Вы видите отредактированный пример из документации vue-router
. Ознакомьтесь с оригиналом в документации, чтобы понять этот код лучше. Если вкратце, то мы просто определяем текущий маршрут и проверяем есть ли у него атрибут meta.requiresAuth
в мета-данных и равно ли его значение true
. Если значение равно true
, это означает, что маршрут требует авторизации для доступа и если пользователь неавторизирован, мы перенаправляем его на страницу входа. Теперь обновите страницу и нажмите на ссылку Dashboard
- вас должно перекинуть на страницу /login
. Все остальные ссылки должны работать как и прежде.
Нам также надо запретить доступ к маршруту /login
авторизированным пользователям. Сейчас мы просто скрываем ссылку, но ничто не мешает пользователю ввести путь напрямую в строку адреса браузера. Уверен, что вы сможете справиться с этой задачей самостоятельно. Отвлекитесь ненадолго от чтения и займитесь воплощением данного функционала в жизнь.
Восстанавливаем данные об аутентификации при загрузке страницы
Мы сохраняем данные в локальном хранилище после успешного входа пользователя, но не считываем эти данные при загрузке страницы (приложения). В результате пользователь перестает быть авторизированным после перезагрузки страницы. Давайте это исправим.
Откройте файл auth.js
. Мы будем считывать данные из локального хранилища в конструкторе (сейчас же мы просто задаем null
переменным).
constructor () {
this.token = window.localStorage.getItem('token');
let userData = window.localStorage.getItem('user');
this.user = userData ? JSON.parse(userData) : null;
if (this.token) {
axios.defaults.headers.common['Authorization'] = 'Bearer ' + this.token;
}
}
Также, чтобы получить доступ к axios
внутри конструктора, нам придется изменить export
модуля в конце файла на следующее:
export default Auth;
И соответствующие изменения в файле app.js
:
import Auth from './auth.js';
window.auth = new Auth();
Готово! Теперь попробуйте войти, обновите страницу и вы будете по-прежнему авторизированы. Хотя, в локальном хранилище могут запросто храниться подставные данные. Было бы неплохо сделать дополнительную проверку прежде, чем мы примем какое-либо решение о статусе пользователя.
Думаю, нам нужно добавить защищенный маршрут в API, который будет возвращать объект авторизированного пользователя исходя из запроса. Если токен в заголовке AJAX запроса окажется неверным, мы разлогиним пользователя на стороне frontend'а. Если токен верный - мы просто обновим информацию о пользователе на случай, если она изменилась на сервере или была изменена в локальном хранилище.
Начнем с frontend'а. Отредактируйте конструктор класса Auth
и вызовите новый метод getUser()
в том случае, если в локальном хранилище был сохранен токен:
if (this.token) {
axios.defaults.headers.common['Authorization'] = 'Bearer ' + this.token;
this.getUser();
}
Этот метод будет просто делать AJAX запрос и обновлять свойство класса user
в случае успеха, или разлогинивать пользователя в случае ответа со статусом 401 "Unauthorized"
.
getUser() {
axios.get('/api/get-user')
.then(({data}) => {
this.user = data;
})
.catch(({response}) => {
if (response.status === 401) {
this.logout();
}
});
}
Теперь backend. Откройте routes/api.php
и добавьте защищенный маршрут /api/get-user
:
...
Route::middleware('auth:api')->group(function () {
Route::post('/logout', 'API\AuthController@logout');
Route::get('/get-user', 'API\AuthController@getUser');
});
Что касается метода в контроллере, то он будет очень простым. Мы просто будем возвращать объект авторизированного пользователя.
public function getUser()
{
return auth()->user();
}
Для проверки авторизируйтесь, задайте левый токен вручную выполнив команду auth.login('token', {});
в консоли браузера, затем обновите страницу. Вас должно разлогинить вскоре после того, как загрузится страница.
Делаем запросы к API
Поздравляю, с аутентификацией наконец-то покончено! Скоро вы сможете приступить к разработке своего приложения. Но сначала, давайте решим проблему, которую я упомянул в предыдущей части урока - нам нужно разлогинивать пользователей после каждого запроса к API, который возвращает ответ со статусом 401 (пользователь может выполнить auth.login('token', {});
уже после изначальной проверки при загрузке страницы). Чтобы это сделать, нам нужно добавлять следующий кусочек к каждому запросу axios:
.catch(({response}) => {
if (response.status === 401) {
this.logout();
}
});
Не очень удобно, правда? Вместо этого давайте напишем метод-обертку для axios, в котором будем добавлять этот кусок ко всем запросам. Мы будем использовать JS Promise (обещание) (если вы не знаете, что это такое - почитайте в интернете). Создайте новый файл resources/assets/js/api.js
:
class Api {
constructor () {}
}
export default Api;
Дальше создайте глобальный объект этого класса в файле app.js
. Ничего нового. Заметьте, что важно поместить строчку window.api = new Api();
ПЕРЕД строкой window.auth = new Auth();
, иначе будет выдаваться ошибка.
import Api from './api.js';
window.api = new Api();
Добавьте новый метод call
в класс Api
:
call (requestType, url, data = null) {
return new Promise((resolve, reject) => {
axios[requestType](url, data)
.then(response => {
resolve(response);
})
.catch(({response}) => {
if (response.status === 401) {
auth.logout();
}
reject(response);
});
});
}
Этот метод делает обычный AJAX запрос с axios, но при этом добавляет логику по-умолчанию для метода catch
. Вы можете использовать этот метод для всех своих запросов к API вместо использования axios напрямую. Вы можете использовать методы catch
и call
так же, как и с axios, при этом условие на проверку кода ответа 401 не будет перезаписано. Отредактируем метод getUser
в файле auth.js
, после чего все должно работать как и прежде:
getUser() {
api.call('get', '/api/get-user')
.then(({data}) => {
this.user = data;
});
}
Заключение
Все готово для того, чтобы начать разрабатывать непосредственно приложение. В реальном проекте вы, скорее всего, организуете ваши JavaScript и Vue файлы немного по-другому. То же можно сказать и про backend. Рекомендую ознакомиться с документацией vue-router, чтобы знать, какие у него еще есть возможности, ибо мы затронули только самое основное. Также вам может пригодиться Vuex, хотя это уже более сложная технология.
Все материалы на сайте voerro абсолютно бесплатны и написаны автором в свободное от основной работы время. Если уроки сайта оказались для вас полезными, пожалуйста, помогите проекту. Спасибо!