Authentication patterns

Backbone.js предоставляет минималистичный каркас для построения клиентских приложений на JavaScript, оставляя разработчику гибкость в реализации логики аутентификации. В этой статье рассматриваются ключевые подходы к организации аутентификации и управления сессиями в приложениях на Backbone.js.


Модели пользователей и хранение состояния

Основой для аутентификации является модель пользователя (User), которая инкапсулирует данные о текущем пользователе и его статусе.

var User = Backbone.Model.extend({
    defaults: {
        id: null,
        username: '',
        token: null,
        isAuthenticated: false
    },

    initialize: function() {
        this.listenTo(this, 'change:isAuthenticated', function(model, value) {
            console.log('Статус аутентификации изменён:', value);
        });
    },

    authenticate: function(credentials) {
        var self = this;
        return $.ajax({
            url: '/api/login',
            method: 'POST',
            data: credentials,
            dataType: 'json'
        }).done(function(response) {
            self.set({
                id: response.id,
                username: response.username,
                token: response.token,
                isAuthenticated: true
            });
        }).fail(function() {
            self.set({ isAuthenticated: false });
        });
    },

    logout: function() {
        this.set({ id: null, username: '', token: null, isAuthenticated: false });
    }
});

Ключевые моменты:

  • Модель хранит токен и идентификатор пользователя, позволяя централизованно управлять статусом аутентификации.
  • Методы authenticate и logout реализуют логику входа и выхода, обновляя состояние модели.
  • Событие change:isAuthenticated позволяет автоматически реагировать на изменения состояния пользователя в приложении.

Работа с сессиями

Для сохранения состояния пользователя между обновлениями страницы используется локальное хранилище (localStorage) или cookies. В Backbone.js удобно использовать сторонние библиотеки, например backbone.localStorage, или напрямую обращаться к window.localStorage.

var Session = Backbone.Model.extend({
    initialize: function() {
        var token = localStorage.getItem('authToken');
        if (token) {
            this.set({ token: token, isAuthenticated: true });
        }
    },

    saveToken: function(token) {
        localStorage.setItem('authToken', token);
        this.set({ token: token, isAuthenticated: true });
    },

    clearToken: function() {
        localStorage.removeItem('authToken');
        this.set({ token: null, isAuthenticated: false });
    }
});

Ключевые моменты:

  • Сессия разделяет ответственность за хранение токена и управление доступом.
  • Автоматическая инициализация при загрузке приложения позволяет восстановить состояние аутентификации.
  • Обновление локального хранилища синхронизируется с моделью.

Ограничение доступа через маршруты

Backbone.Router позволяет контролировать доступ к страницам в зависимости от статуса пользователя:

var AppRouter = Backbone.Router.extend({
    routes: {
        'dashboard': 'showDashboard',
        'login': 'showLogin'
    },

    initialize: function(options) {
        this.user = options.user;
    },

    showDashboard: function() {
        if (!this.user.get('isAuthenticated')) {
            this.navigate('login', { trigger: true });
            return;
        }
        console.log('Отображение панели пользователя');
    },

    showLogin: function() {
        console.log('Отображение страницы входа');
    }
});

Ключевые моменты:

  • Проверка isAuthenticated перед показом защищённых маршрутов.
  • Перенаправление на страницу входа при отсутствии аутентификации.
  • Router и модель пользователя тесно связаны, что упрощает централизованное управление состоянием.

Интеграция с REST API

Backbone.js тесно интегрирован с RESTful API. Для аутентификации это означает передачу токена через заголовки:

var AuthenticatedModel = Backbone.Model.extend({
    sync: function(method, model, options) {
        options = options || {};
        options.beforeSend = function(xhr) {
            if (model.get('token')) {
                xhr.setRequestHeader('Authorization', 'Bearer ' + model.get('token'));
            }
        };
        return Backbone.sync(method, model, options);
    }
});

Ключевые моменты:

  • Переопределение sync позволяет автоматически добавлять токен к каждому запросу.
  • Это облегчает работу с защищёнными ресурсами без дублирования кода.
  • Такой подход стандартизирует взаимодействие с сервером и повышает безопасность приложения.

Паттерн «Observer» для реактивного интерфейса

Использование событий Backbone позволяет интерфейсу автоматически обновляться при изменении статуса аутентификации:

var UserView = Backbone.View.extend({
    initialize: function() {
        this.listenTo(this.model, 'change:isAuthenticated', this.render);
    },

    render: function() {
        if (this.model.get('isAuthenticated')) {
            this.$el.html('Привет, ' + this.model.get('username'));
        } else {
            this.$el.html('<a href="#login">Войти</a>');
        }
        return this;
    }
});

Ключевые моменты:

  • Модель пользователя выступает источником истины, а представление реагирует на изменения.
  • Поддержка реактивного интерфейса без сложной логики обновления DOM.
  • Позволяет гибко управлять отображением разных состояний интерфейса.

Комбинирование паттернов

Эффективная аутентификация в Backbone.js обычно строится на комбинации нескольких подходов:

  • Модель пользователя (User) для управления состоянием и методами аутентификации.
  • Модель сессии (Session) для хранения токена и восстановления состояния.
  • Router для ограничения доступа к защищённым маршрутам.
  • Переопределение sync для автоматической передачи токена при запросах к API.
  • Observer-паттерн для динамического обновления интерфейса на основе изменений модели.

Такой подход позволяет построить модульную, расширяемую и безопасную архитектуру аутентификации, полностью интегрированную в клиентскую часть приложения на Backbone.js.