一种解决方案是将授权令牌作为变量存储在您的应用中。例如,
// app.js
var app = {
views: {},
models: {},
collections: {},
routers: {},
utils: {},
adapters: {},
session: {}
};
当用户登录时,服务器会将 Devise.friendly_token 发送回客户端。您可以将该访问令牌保存在应用程序中并保护自己免受 CSRF 攻击。但是,如果攻击者有权访问用户的浏览器,此方法确实会使您面临其他类型的攻击。
// LoginView.js
app.views.LoginView = Backbone.View.extend({
// ...
login: function(event){
var data = new FormData();
data.append('email', $('#email').val());
data.append('password', $('#password').val());
$.ajax({
url: API_ROOT + "api/v1/login",
data: data,
type: 'POST',
success: function(data){
app.session.userEmail = data.email;
app.session.userAccessToken = data.access_token;
},
error: function(data){
alert('Login failed');
}
});
},
// ...
});
存储令牌后,将其与您的请求一起在授权标头中发送到您的 API 服务器。
Backbone.sync = function(method, model, options) {
// ... override the Backbone.sync function. See the annotated source code for more
// info.
options.beforeSend = function(xhr) {
xhr.setRequestHeader('Authorization', ("" + app.session.userAccessToken));
}
//... also send for POST
if (options.emulateHTTP && (type === 'PUT' || type === 'DELETE' || type === 'PATCH')) {
params.type = 'POST';
if (options.emulateJSON) params.data._method = type;
var beforeSend = options.beforeSend;
options.beforeSend = function(xhr) {
xhr.setRequestHeader('X-HTTP-Method-Override', type);
xhr.setRequestHeader('Authorization', ("" + app.session.userAccessToken));
if (beforeSend) return beforeSend.apply(this, arguments);
};
}
//...
};
这种方法远非完美,因为它允许访问浏览器的攻击者获取用户的访问令牌。添加额外安全层的一种方法可能是在服务器端间隔一段时间后更新访问令牌。希望这至少可以开始一些关于更好地实现这一点的讨论。