将会话参数保存在Cookie中 [英] Save session parameters in cookies

查看:216
本文介绍了将会话参数保存在Cookie中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的Backbone.js应用程序,它使用 json-server 作为后端.我有一个登录功能,可以从集合中查找用户,但是我不知道如何保存会话.我考虑过将参数存储在cookie中,以后将在每次重定向时对其进行检查.这是我的模型:

I've got a simple Backbone.js app which uses json-server as a backend. I have a function to log in, that finds a user from the collection, but I don't get how will I save my session. I thought about storing a parameter in cookies that later will be checked on every redirect. Here is my model:

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});
    }
});

这是具有登录功能的视图

And this is the view with login function

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中,以便可以在应用程序中的其他地方使用它,但是我实际上并没有怎么做.

This function returns me an array with one object that is my requested model. All that I need is to use my setToken method and to save this model's authToken in cookie so that I could use it elsewhere in app, but I don't actually get how to do that.

推荐答案

使用模型处理身份验证比集合有意义.使模型的职责简单,并只限于一件事.一个模型来处理身份验证,然后一个模型来处理对需要验证的其他对象的调用,而不是一次完成.

Using a model to handle authentication would make more sense than a collection. Keep the model's responsibility simple and scoped to one thing. A model to handle the authentication, then a model to handle calls to other object which needs to be authenticated, not both at once.

我个人基于骨干会话的模型进行身份验证.

I personally based authentication on Backbone-session's model.

// 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的以下每个调用均经过验证.

Which I expose as a service to my application. In this session module, I override Backbone.Sync to ensure auth for each following calls to the API for any models or collection.

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方法被覆盖以使用本地存储,而不是默认的sync行为.

Backbone-session's model uses the local storage as a backend. Its own sync method is overriden to use the local storage instead of the default sync behavior.

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.

Why the local storage?

You could use this implementation and change it minimally to use cookies instead.

对我来说,本地存储是一个更好的选择,因为我的API在另一个域上,并使用CORS启用公共访问. Safari对cookie有所限制.

The local storage was a better option for me since my API is on another domain and uses CORS to enable public access. Safari has limitation on cookies.

Safari还会阻止尚未访问的站点的cookie 直接地.您可以在安全设置中看到.这是默认设置 是接受Cookie":仅来自我访问的网站".

Safari also blocks cookies from sites that haven't been visited directly. You can see in the security settings. It's default setting is Accept cookies: "Only from sites I visit".

这篇关于将会话参数保存在Cookie中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆