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,这是一个安全风险。我一直在搜索,但看到的替代方案很少:
- 如果尝试失败,return 来自服务器的新令牌并重新提交表单
- 在提交表单之前,进行 ajax GET 调用以检索新令牌
- 将令牌添加到登录控制器上的请求headers
如果我对安全风险的理解正确,我看不出这些解决方案是如何解决安全问题的。我的意思是,据我了解,未受保护登录的风险 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'"/>
我们在将 session 移动到 Redis 时开始出现 CSRF 令牌问题。问题是用户 sign-out,并长时间离开登录屏幕,例如过夜。然后,在早上,第一次登录尝试总是失败,因为表单 CSRF 令牌不再有效,因为 redis session 已从服务器 (TTL) 中删除。
我在网上搜索了几个小时,但不确定怎样做才是正确的。添加此文件可解决问题:
class SessionsController < Devise::SessionsController
skip_before_filter :require_no_authentication, only: [:new]
end
但据我所知 read online,这是一个安全风险。我一直在搜索,但看到的替代方案很少:
- 如果尝试失败,return 来自服务器的新令牌并重新提交表单
- 在提交表单之前,进行 ajax GET 调用以检索新令牌
- 将令牌添加到登录控制器上的请求headers
如果我对安全风险的理解正确,我看不出这些解决方案是如何解决安全问题的。我的意思是,据我了解,未受保护登录的风险 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'"/>