【问题标题】:Save session parameters in cookies在 cookie 中保存会话参数
【发布时间】:2016-10-18 01:21:31
【问题描述】:

我有一个简单的 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 中,以便我可以在应用程序的其他地方使用它,但我实际上不知道如何做到这一点。

【问题讨论】:

    标签: javascript cookies backbone.js


    【解决方案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:“仅来自我访问的网站”。

    【讨论】:

      猜你喜欢
      • 2017-02-25
      • 1970-01-01
      • 1970-01-01
      • 2018-05-26
      • 1970-01-01
      • 1970-01-01
      • 2020-10-20
      • 2012-02-22
      • 2014-03-24
      相关资源
      最近更新 更多