在 cookie 中保存 session 个参数
Save session parameters in cookies
我有一个简单的 Backbone.js 应用程序,它使用 json-server 作为后端。我有一个登录功能,可以从 collection 中找到一个用户,但我不知道如何保存我的 session。我考虑过在 cookie 中存储一个参数,稍后将在每次重定向时检查该参数。这是我的模型:
var User = Backbone.Model.extend({
defaults: {
login: '',
password: '',
authToken: ''
}
});
这是我的 collection:
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
}
});
}
}
});
这个函数 returns 给我一个数组,其中一个 object 是我请求的模型。我所需要的只是使用我的 setToken
方法并将此模型的 authToken
保存在 cookie 中,以便我可以在应用程序的其他地方使用它,但我实际上并不知道该怎么做。
使用模型来处理身份验证比集合更有意义。保持模型的职责简单并限定在一件事上。一个模型来处理身份验证,然后是一个模型来处理对其他需要进行身份验证的对象的调用,而不是同时进行。
我个人根据 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 来启用 public 访问。 Safari has limitation on cookies.
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".
我有一个简单的 Backbone.js 应用程序,它使用 json-server 作为后端。我有一个登录功能,可以从 collection 中找到一个用户,但我不知道如何保存我的 session。我考虑过在 cookie 中存储一个参数,稍后将在每次重定向时检查该参数。这是我的模型:
var User = Backbone.Model.extend({
defaults: {
login: '',
password: '',
authToken: ''
}
});
这是我的 collection:
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
}
});
}
}
});
这个函数 returns 给我一个数组,其中一个 object 是我请求的模型。我所需要的只是使用我的 setToken
方法并将此模型的 authToken
保存在 cookie 中,以便我可以在应用程序的其他地方使用它,但我实际上并不知道该怎么做。
使用模型来处理身份验证比集合更有意义。保持模型的职责简单并限定在一件事上。一个模型来处理身份验证,然后是一个模型来处理对其他需要进行身份验证的对象的调用,而不是同时进行。
我个人根据 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 来启用 public 访问。 Safari has limitation on cookies.
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".