Backbone.js не содержит встроенного механизма аутентификации и авторизации, что принципиально соответствует его философии: фреймворк отвечает за структуру клиентского приложения, а не за бизнес-логику безопасности. Реализация этих аспектов полностью ложится на архитектуру приложения и взаимодействие с сервером. Это позволяет гибко адаптировать решения под любые протоколы — от сессионной авторизации до JWT и OAuth.
Authentication (аутентификация) — процесс подтверждения личности пользователя. Authorization (авторизация) — процесс определения прав доступа уже аутентифицированного пользователя.
В Backbone-приложении эти процессы всегда связаны с сервером, но клиент отвечает за:
Типовая структура включает:
Ключевая идея: состояние авторизации должно быть централизовано и доступно всему приложению.
Чаще всего используется отдельная модель, представляющая текущую сессию:
var CurrentUser = Backbone.Model.extend({
url: '/api/session',
defaults: {
authenticated: false,
role: null,
permissions: []
},
isAuthenticated: function() {
return this.get('authenticated') === true;
},
hasPermission: function(permission) {
return this.get('permissions').includes(permission);
}
});
Эта модель:
Типовой сценарий:
Пример View для логина:
var LoginView = Backbone.View.extend({
events: {
'submit form': 'login'
},
login: function(e) {
e.preventDefault();
var credentials = {
email: this.$('[name=email]').val(),
password: this.$('[name=password]').val()
};
$.post('/api/login', credentials)
.done(function(data) {
currentUser.set(data);
})
.fail(function() {
// обработка ошибки
});
}
});
Важно, что View не хранит состояние авторизации — оно принадлежит модели.
При использовании серверных сессий:
Преимущество — минимальная логика на клиенте. Недостаток — сложность масштабирования и CSRF.
При использовании токенов:
localStorage или
sessionStorage;Расширение Backbone.sync:
var originalSync = Backbone.sync;
Backbone.sync = function(method, model, options) {
options = options || {};
options.headers = options.headers || {};
var token = localStorage.getItem('token');
if (token) {
options.headers.Authorization = 'Bearer ' + token;
}
return originalSync.call(this, method, model, options);
};
Такой подход делает авторизацию прозрачной для всех моделей и коллекций.
При старте приложения выполняется запрос к серверу:
currentUser.fetch({
success: function() {
appRouter.start();
},
error: function() {
appRouter.start();
}
});
Даже при ошибке загрузки маршрутизатор запускается, но состояние пользователя остаётся неаутентифицированным.
Backbone.Router не поддерживает guards из коробки, но они легко реализуются:
var AppRouter = Backbone.Router.extend({
routes: {
'admin': 'adminPanel',
'login': 'login'
},
adminPanel: function() {
if (!currentUser.isAuthenticated()) {
this.navigate('login', { trigger: true });
return;
}
if (!currentUser.hasPermission('admin')) {
this.navigate('', { trigger: true });
return;
}
// загрузка admin view
}
});
Таким образом:
Помимо маршрутов, контроль доступа часто требуется внутри интерфейса.
Пример условного рендера:
render: function() {
this.$el.html(this.template(this.model.toJSON()));
if (!currentUser.hasPermission('edit')) {
this.$('.edit-button').remove();
}
return this;
}
Такой подход не заменяет серверную проверку, но улучшает UX и предотвращает ошибочные действия.
Сервер должен возвращать корректные HTTP-коды:
401 Unauthorized — не аутентифицирован;403 Forbidden — нет прав.Глобальная обработка:
$(document).ajaxError(function(e, xhr) {
if (xhr.status === 401) {
appRouter.navigate('login', { trigger: true });
}
});
Это позволяет централизованно реагировать на потерю сессии или истечение токена.
Процесс выхода:
function logout() {
localStorage.removeItem('token');
currentUser.clear().set(currentUser.defaults);
appRouter.navigate('login', { trigger: true });
}
Важно полностью очищать состояние, чтобы избежать утечек прав.
Иногда доступ зависит от конкретного ресурса:
var Document = Backbone.Model.extend({
canEdit: function() {
return currentUser.hasPermission('edit_document') &&
this.get('owner_id') === currentUser.id;
}
});
Это позволяет инкапсулировать бизнес-логику рядом с данными.
При изменении прав пользователя:
CurrentUser обновляется;change.currentUser.on('change', function() {
appView.render();
});
Backbone-событийная модель делает такие сценарии предсказуемыми и управляемыми.
Клиентская авторизация:
Любые критические проверки всегда выполняются сервером, а Backbone используется как слой координации и представления состояния.
Такая структура остаётся масштабируемой, тестируемой и не привязанной к конкретному протоколу аутентификации.