身份验证是应用程序的责任。
对于 Backbone 应用程序,身份验证逻辑应该在 Backbone 代码中,并且应该不惜一切代价避免更改全局 jQuery 的行为。ajax
ajaxSetup
或的缺点ajaxSend
来自 jQuery 文档ajaxSetup
:
注意:此处指定的设置将影响对所有调用$.ajax
或基于 Ajax 的派生类的调用,例如$.get()
. 这可能会导致不良行为,因为其他调用者(例如插件)可能期望正常的默认设置。因此,我们强烈建议不要使用此 API。相反,请在调用中明确设置选项或定义一个简单的插件来执行此操作。
ajaxSend
和上面提到的有同样的问题。它的唯一优势ajaxSetup
是每次都调用一个函数,比传递给ajaxSetup
.
最安全的方法,AuthModel
和AuthCollection
将身份验证逻辑放入基本模型和集合中。这是范围最广的解决方案。
在这里,您可以使用您已经存在的BaseModel
,但我仍然倾向于将 与 分开,BaseModel
因为AuthModel
您可能希望创建一个自定义模型,该模型使用您的基本模型,但也使用不同的外部 API。
由于模型和集合的新sync
函数相似,但两者可能有不同的父实现,我做了一个简单的函数生成器。
/**
* Generates a new sync function which adds the token to the request header
* and handles a redirect on error.
* @param {Function} syncFn the parent `sync` function to call.
* @return {Function} a new version of sync which implements the auth logic.
*/
var authSyncFunction = function(syncFn) {
return function(method, model, options) {
options = options || {};
var beforeSend = options.beforeSend,
error = options.error;
_.extend(options, {
// Add auth headers
beforeSend: function(xhr) {
xhr.setRequestHeader('Authorization', "Bearer " + yourTokenHere);
if (beforeSend) return beforeSend.apply(this, arguments);
},
// handle unauthorized error (401)
error: function(xhr, textStatus, errorThrown) {
if (error) error.call(options.context, xhr, textStatus, errorThrown);
if (xhr.status === 401) {
Backbone.history.navigate('login');
}
}
});
return syncFn.call(this, method, model, options);
};
};
在模型和集合上使用生成器。
var AuthModel = BaseModel.extend({
sync: authSyncFunction(BaseModel.prototype.sync)
});
var AuthCollection = BaseCollection.extend({
sync: authSyncFunction(BaseCollection.prototype.sync)
});
然后您就可以在您确定需要身份验证的模型和集合上使用它们了。由于您已经在使用基本模型和集合,因此只需BaseModel.extend
将AuthModel.extend
.
虽然我知道您要求对403 Forbidden
响应进行重定向,但我认为它应该在401 Unauthorized
. 请参阅403 Forbidden 与 401 Unauthorized HTTP 响应
覆盖主干sync
如果您此时不想更改所有模型和集合,但仍想遵循良好实践并避免更改全局 ajax 设置,则覆盖该Backbone.sync
函数是一个简单的选择。
使用我们之前定义的sync
生成器:
Backbone.sync = authSyncFunction(Backbone.sync);
管理本地存储和身份验证
要管理本地存储中的数据,请检查Backbone-session。
这是一个很好的 Backbone 模型实现,它与本地存储而不是 REST API 同步。它还提供了一个很好的界面来管理身份验证。
// Extend from Session to implement your API's behaviour
var Account = Session.extend({
signIn: function () {},
signOut: function () {},
getAuthStatus: function () {}
});
// Using the custom Account implementation
var session = new Account();
session.fetch()
.then(session.getAuthStatus)
.then(function () {
console.log('Logged in as %s', session.get('name'));
})
.fail(function () {
console.log('Not yet logged in!');
});