会话到期后无法验证CSRF令牌的真实性 - Rails + devise + redis

时间:2017-02-24 17:37:55

标签: ruby-on-rails security devise csrf

我们在将会话移至Redis时启动的CSRF令牌存在问题。问题是用户退出并长时间离开登录屏幕,例如过夜。然后,在早上,第一次登录尝试总是失败,因为表单CSRF令牌不再有效,因为redis会话已从服务器(TTL)中删除。

我在网上搜索了几个小时,但不确定什么是正确的方法。添加此文件可以解决问题:

class SessionsController < Devise::SessionsController
  skip_before_filter :require_no_authentication, only: [:new]
end

但是从我read online开始,这是一个安全风险。我一直在寻找,看到了一些替代方案:

  • 尝试失败,从服务器返回新令牌并重新提交表单
  • 在提交表单之前,进行ajax GET调用以检索新令牌
  • 将令牌添加到登录控制器上的请求标头

如果我正确理解了安全风险,我看不出这些解决方案是如何解决安全问题的。我的意思是,从我读到的不受保护的登录API的风险是,攻击者可以诱骗其他人登录攻击者配置文件并输入私人数据,然后攻击者可以使用这些数据。因此,对于任何这些解决方案,攻击者都可以模仿相同的行为并自我攻击,对吧?

解决此问题的最安全方法是什么?

2 个答案:

答案 0 :(得分:0)

我通过添加API来修复它以获取新令牌并在登录表单打开很长时间时使用它。代码:

应用/控制器/ my_controller.rb:

def token
  render json: { token: form_authenticity_token }, status: :ok
end

<强> signin.html:

$('form#login').submit(function(e) {
    var that = this;
    e.preventDefault();
    // assuming the session TTL is 30 min
    if (new Date() - window.loginPageRenderedAt > 1800000) {
      $.get('token', function(data) {
        var token = data.token;
        $('input[name=authenticity_token]').val(token)
        that.submit();
      }).fail(function() {
        that.submit();
      })
    } else {
      this.submit();
    }
}

答案 1 :(得分:0)

所选答案增加了潜在的安全风险。考虑一下用户在登录页面上输入其凭据并使其保持打开状态的情况,我认为这是被规避的令牌的好处之一。当然,javascript 可以重置字段。这是另一个不需要任何其他内容的简单解决方案,请将其添加到0中的标头中:

app/views/layouts/devise_layout.html.erb