将Auth Token安全存储在Backbone应用程序中

时间:2015-02-23 05:00:17

标签: ruby-on-rails authentication backbone.js token marionette

我在Rails应用程序上启动Marionette,我正在寻找一种安全的方式来验证请求。我确信很多人都做过这件事,但我找不到令人满意的答案:(

以下是我迄今为止所发现的内容:

  • 在rails中,我可以使用Devise.friendly_token生成令牌,将其保存在数据库中并将其发送给客户端。
  • 客户端可以将令牌存储在从CSRF保护的页面的元数据中。
  • 在每次请求时,客户端都会使用

    在标头中发送令牌

    var token = $("meta[name='csrf-token']").attr("content"); xhr.setRequestHeader("X-CSRF-Token", token);

并且服务器将比较令牌以验证请求。到目前为止一切都很好。

  • 我在不同的地方读过Cookie很容易受到跨域请求的攻击。但是持久性cookie似乎是持久会话的唯一解决方案。我如何以安全的方式使用它们?

  • 另一方面,我发现建议在将密码发送到服务器之前在客户端散列密码。对于基于API的服务,有什么兴趣?

谢谢!

1 个答案:

答案 0 :(得分:2)

一种解决方案是将授权令牌作为变量存储在您的应用中。例如,

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

//...
};

这种方法远非完美,因为它允许访问浏览器的攻击者获取用户的访问令牌。添加额外安全层的一种方法可能是在服务器端的间​​隔之后更新访问令牌。希望至少开始讨论更好的方法来实现这一点。