我试图创建一个"资产控制器"垫片将过滤静态资产请求,因此只有授权用户才能检索某些资产。我想继续使用资产管道,所以我设置了这样的路线
get 'assets/*assetfile' => 'assets#sendfile'
然后我用一个方法" sendfile"创建了一个AssetsController。将其剥离到只有重要的东西,它看起来像这样:
class AssetsController < ApplicationController
def sendfile
# Basically the following function forces the file
# path to be Rails.root/public/assets/basename
assetfilename=sanitize_filename(params[:assetfile] + '.' + params[:format])
send_file(assetfilename)
end
end
看起来我必须在生产模式下运行它,因为rails会绕过开发中的资产路径。所以我预先编译了我的资产,我可以在控制器中验证文件是否存在于预期的位置。
然而,现在的问题是我得到了一个&#34; ActionController :: InvalidCrossOriginRequest&#34;当请求Javascript资产时(现在只使用默认的应用程序。*资产)。我已经读过这个错误了,据我所知,从Rails 4.1开始,Javascript资产有一些特殊的跨源保护。对我来说听起来不错,但我不明白&#34;跨越起源&#34;部分来自。使用firebug,我可以看到正在从与原始页面相同的域请求资产请求。
我确信这是问题,因为我可以通过放置&#34; skip_before_action:verify_authenticity_token&#34;来解决它。在我的控制器的开头。但是,我真的不想这样做(我不完全理解为什么这项检查是必要的,但我确定有很好的理由)。
application.html.erb文件与默认生成的文件相同,因此我假设它在发出请求时发送了CSRF令牌,就像我没有自己的控制器一样对于资产。
那么我错过了什么?
答案 0 :(得分:2)
好吧,我想我回答了自己的问题(令人不满意)。再次,长篇大论,所以请耐心等待。我错误地忘记将其添加到我原来的问题中,但我使用的是Ruby 2.2.0和Rails 4.2.4。
通过查看“actionpack-4.2.4 / lib / action_controller / metal / request_forgery_protection.rb”中的代码,看起来Rails正在进行两次检查。第一项检查是“verify_authenticity_token”方法,该方法对POST请求的真实性令牌进行预期验证。对于GET请求,它还设置一个标志,该标志导致对请求形成的计算响应进行第二次检查。
对响应的检查只是说如果请求不是XHR(AJAX)请求并且响应的MIME类型是“text / javascript”,则引发“ActionController :: InvalidCrossOriginRequest”,这是错误我到了。
我通过在“send_file”中将“.js”文件的类型设置为“application / javascript”来验证这一点。这是代码:
if request.format.js?
send_file(assetfilename, type: 'application/javascript')
else
send_file(assetfilename)
end
我可以通过在控制器类的顶部添加以下行来跳过响应检查:
skip_after_action :verify_same_origin_request
对我的反应检查似乎相当弱,目前尚不清楚这是如何真正提供针对CSRF的进一步保护。但我会在另一个问题上发布这个问题。