然而,我们发现,如果用户访问登录页面,然后在应用程序会话到期时间(假设15分钟)的时间内关闭一杯茶.无论登录页面是否成功,登录名都将重定向到登录页面(根据环境,我们收到错误InvalidAuthenticityToken.)尝试再次登录工作正常.只有当用户在页面上的时间超过会话时间时,它才会失败.
我们认为这是奇怪的,因为我们还没有登录…所以什么会话到期?并且肯定会在登录时创建一个新的会话,即使创建并已过期.结果(阅读完之后:https://nvisium.com/blog/2014/09/10/understanding-protectfromforgery/),Rails中的CSRF保护实际上使用会话来检查authenticity_token是否有效.因此,当会话过期时(基于session_store设置),基本上该令牌将过期,并且您无法再次刷新页面时无法登录.
我们解决了这一点:skip_before_action:verify_authenticity_token,只有:[:create]在我们的SessionsController中,但现在这意味着我们的登录表单不再受保护.
还有什么其他选择来解决这个问题?或者我们使用的解决方案并不像我们认为的那样不安全?谷歌在这段代码中使用了很多次,但肯定是一个坏主意?
我们的其他解决方案是允许异常发生,但是可以通过以下方式处理:
rescue_from ActionController::InvalidAuthenticityToken do @exception = exception.message render 'errors/500',:status => 500,:layout => 'other' end
虽然仍然讨厌用户坐在登录页面上的时间超过会话超时(在这种情况下为15分钟)会导致错误!
我们提出的另一个解决方案是将session_store设置为永久,然后手动过期登录会话,如下所示:
before_action :session_timeout,if: :current_user def session_timeout session[:last_seen_at] ||= Time.now if session[:last_seen_at] < 15.minutes.ago reset_session else session[:last_seen_at] = Time.now end end
解决方法
so what session is expiring?
相关会话是Rails会话(参见Ruby on Rails Security Guide中的What are Sessions?),它是一种轻量级的数据存储抽象,可以跨HTTP请求持续任意状态(默认情况下,加密的cookie也可以配置其他会话存储实现).会话状态可以包括认证用户ID,但也可以用于其他目的.
在这种情况下,会话不会用于用户身份验证,而是将临时“真实性令牌”存储为Rails安全功能的一部分,以保护您的网站免受POST(或其他非GET)请求的Cross-Site Request Forgery(CSRF)攻击.
Rails API documentation更详细地描述了此功能:
Controller actions are protected from Cross-Site Request Forgery (CSRF) attacks by including a token in the rendered HTML for your application. This token is stored as a random string in the session,to which an attacker does not have access. When a request reaches your application,Rails verifies the received token with the token in the session.
另请参阅Ruby on Rails Security Guide的Cross-Site Request Forgery部分,以更全面地了解CSRF攻击是什么,以及基于会话的真实性 – 令牌验证如何保护它.
What other options are there to fix this?
>增加您的Rails会话到期时间(例如,通过增加传递给您的cookie_store初始化程序的expire_after选项的持续时间,或完全删除该选项,使会话永不过期).
>而不是使用session-cookie过期到期登录会话,请使用Devise的:可超时模块:
devise :timeoutable,timeout_in: 15.minutes
Or is the solution we have used not as insecure as we think?
配置Rails以跳过verify_authenticity_token回调将禁用针对该特定控制器操作的CSRF保护,这使得该操作容易受到CSRF攻击.
所以要重新表达你的问题,是否只对SessionsController#创建CSRF保护措施在任何重大/有意义的意义上仍然不安全?虽然这取决于你的申请,但一般来说,我相信.
考虑这种情况:
针对SessionsController#create的CSRF攻击将允许攻击者恶意地指示受害者的浏览器在攻击者的控制下登录到用户帐户.下一次受害者访问您的网站(例如,当被攻击者重定向时),他们的浏览器仍然可以登录到攻击者控制的帐户.受害者可能不知不觉地在您的网站上提交敏感的个人数据或对您的网站执行敏感操作,这些操作可能被攻击者读取.
虽然这种情况可能不如在CSRF保护在其他更敏感/破坏性的控制器操作上被禁用时可能会发生什么危险,但它仍然暴露了足够的潜在的用户/数据隐私问题,我认为它是不够安全的,以推荐反对禁用默认保护.