将会话参数保存在cookie中

时间:2016-10-17 13:59:22

标签: javascript cookies backbone.js

我有一个简单的Backbone.js应用程序,它使用json-server作为后端。我有一个登录的功能,从集合中找到一个用户,但我不知道如何保存我的会话。我考虑过在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中,以便我可以在app中的其他地方使用它,但我实际上并没有得到如何做到这一点。

1 个答案:

答案 0 :(得分: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   直。您可以在安全设置中看到。它的默认设置   是接受cookie:"仅限我访问的网站"。