2016-10-17 3 views
1

У меня есть простое приложение Backbone.js, которое использует json-server в качестве бэкэнд. У меня есть функция входа в систему, которая находит пользователя из коллекции, но я не понимаю, как сохранить сеанс. Я думал о сохранении параметра в файлах cookie, которые позже будут проверяться при каждом перенаправлении. Вот моя модель:Сохранение параметров сеанса в файлах cookie

var User = Backbone.Model.extend({ 
    defaults: { 
     login: '', 
     password: '', 
     authToken: '' 
    } 
}); 

И вот моя коллекция:

var UserCollection = Backbone.Collection.extend({ 
    url: 'http://localhost:3000/users', 

    // creates a random token 
    setToken: function() { 
     var rand = function() { 
      return Math.random().toString(36).substr(2) 
     } 

     var token = rand() + rand(); 
     this.set({authToken: token}); 
    } 
}); 

И это вид с функцией входа

var LoginView = Backbone.View.extend({ 
    initialize: function() { 
     this.collection = new UserCollection(); 
     // template 
    } 
    // render function omitted 

    signIn: function() { 
     var login = $('#login').val(); 
     var password = $('#password').val(); 

     /** 
      finds a user within with the values from input fields 
      inside the collection 
     */ 
     if (login && password) { 
      this.collection.fetch({ 
       data: { 
        login: login, 
        password: password 
       } 
      }); 
     } 
    } 
}); 

Эта функция возвращает мне массив с одним объектом, это моя запрошенная модель. Все, что мне нужно, это использовать мой метод setToken и сохранить authToken этой модели в файле cookie, чтобы я мог использовать его в другом месте приложения, но на самом деле я не понимаю, как это сделать.

ответ

1

Использование модели для аутентификации будет иметь больше смысла, чем сбор. Следите за тем, чтобы ответственность модели была простой и ограниченной для одной вещи. Модель для обработки аутентификации, а затем модель для обработки вызовов на другой объект, который должен быть аутентифицирован, а не одновременно.

Я лично установил подлинность на модели Backbone-session.

// Using CommonJS 
var Session = require('backbone-session'); 

// Extend from Session to implement your API's behaviour 
var Account = Session.extend({ 
    urlRoot: 'http://localhost:3000/users', 
    signIn: function(opt) { 
     opt = opt || {}; 
     opt.data = _.extend({}, { 
      login: opt.login, 
      password: opt.password 
     }, opt.data); 
     return this.fetch(opt); 
    }, 
    signOut: function(opt) { /** handle logout */ }, 
    getAuthStatus: function() { /** handle refetching if needed */ } 
}); 

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

var mySession = new Account(); 


Backbone.sync = (function(syncFn) { 
    return function(method, model, options) { 
     options = options || {}; 

     var beforeSend = options.beforeSend, 
      error = options.error; 

     // Add auth headers 
     options.beforeSend = function(xhr) { 
      xhr.setRequestHeader('Authorization', "Bearer " + mySession.get('authToken')); 
      if (beforeSend) return beforeSend.apply(this, arguments); 
     }; 

     // handle unauthorized error (401) 
     options.error = function(xhr, textStatus, errorThrown) { 
      if (error) error.call(options.context, xhr, textStatus, errorThrown); 
      if (xhr.status === 401) { 
       mySession.signOut(); 
      } 
     }; 

     return syncFn.apply(this, arguments); 
    }; 
})(Backbone.sync); 

Модель Backbone-session использует локальное хранилище в качестве бэкэнд. Его собственный sync method is overriden использовать локальное хранилище вместо по умолчанию sync.

sync: function(method, model, options) { 
    options = options || {}; 
    var url = model.options.url || model.url; 
    var key = _.isFunction(url) ? url() : '' + url; 
    var response; 
    switch (method) { 
    case 'create': 
    case 'update': 
     var data = model.toJSON(); 
     var text = JSON.stringify(data); 
     response = localStorage.setItem(key, text); 
     break; 
    case 'delete': 
     response = localStorage.removeItem(key); 
     break; 
    case 'read': 
     response = JSON.parse(localStorage.getItem(key)); 
     break; 
    } 
    if (_.isFunction(options.success)) { 
    options.success(response); 
    } 
    return Backbone.$.Deferred() 
    .resolve(response) 
    .promise(); 
}, 

Почему локальное хранилище?

Вы можете использовать эту реализацию и минимально использовать ее для использования файлов cookie.

Локальное хранилище было лучшим вариантом для меня, так как мой API находится в другом домене и использует CORS для обеспечения открытого доступа. Safari has limitation on cookies.

Safari также блокирует куки с сайтов, которые не посещали непосредственно. Вы можете увидеть настройки безопасности. По умолчанию установлено значение . Принимать файлы cookie: «Только с сайтов, которые я посещаю».