session 过期后无法验证 CSRF 令牌真实性 - Rails + 设计 + redis

can't verify CSRF token authenticity after session expires - Rails + devise + redis

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

我在网上搜索了几个小时,但不确定怎样做才是正确的。添加此文件可解决问题:

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

但据我所知 read online,这是一个安全风险。我一直在搜索,但看到的替代方案很少:

如果我对安全风险的理解正确,我看不出这些解决方案是如何解决安全问题的。我的意思是,据我了解,未受保护登录的风险 API 是攻击者可以诱骗其他人登录攻击者个人资料并输入私人数据,然后攻击者可以使用这些数据。因此,使用这些解决方案中的任何一种,攻击者都可以模仿相同的行为并入侵自己,对吗?

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

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

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

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

<meta http-equiv="refresh" content="3600;URL='/users/sign_in'"/>