0

我正在使用 Sinatra 并使用 sinatra-authentication gem 进行身份验证,以及自定义表单(如联系表单)。

为了帮助解决 CSRF 问题,我设计了一个小解决方案,可以使用来自 sinatra-authentication 的预定义路由以及自定义路由。

before do
  if request.post?
    if session[:csrf] != params[:csrf]
      halt 503, erb('<h1>500: oops</h1>')
    end
  end 

  time = Time.now.to_s
  @key = Digest::SHA1.hexdigest(time)
  session[:csrf] = @key
end

因此,在每个页面请求上,它都会设置一个会话,该会话是当前时间的哈希值。这个散列也使用隐藏元素设置到每个表单<input type="hidden" name="csrf" value="<%= @key %>" />。提交表单时,它会在原始表单中before检查存储在会话中的项目,并将提交的项目作为隐藏值。简单的!

但是...这在 localhost 上运行良好,在我的 herokuapp.com 域上运行良好,在我的www域上运行良好(这是 herokuapp.com 域的 cname),但它不适用于non-www域(这是 A 记录对于 Heroku 的 IP 集)。

我能看到的唯一区别是non-wwwDNS 中具有 A 记录的域似乎正在设置清漆标头,因此必须在某处通过清漆,但由于会话在 rack.session 内,我想知道清漆是否正在过滤这个出去。

那么最终,为什么要if session[:csrf] != params[:csrf]返回true

4

0 回答 0