我对在Thread.current
哈希中存储信息的做法(例如,current_user,当前子域等)持续存在冲突。已经提出该技术作为简化模型层内的后续处理的方法(查询范围,审计等)。
许多人认为这种做法不可接受,因为它破坏了MVC模式。 其他人表达了对方法可靠性/安全性的担忧,我的两部分问题集中在后一方面。
Thread.current
哈希是否保证在整个周期内只有一个响应可用且是私有的?
据我所知,在响应结束时,一个线程可能会被移交给其他传入请求,从而泄露Thread.current
中存储的任何信息。是否会在响应结束前清除此类信息(例如,通过从控制器的Thread.current[:user] = nil
执行after_filter
)来防止此类安全漏洞?
谢谢! 朱塞佩
答案 0 :(得分:43)
没有特别的理由远离线程局部变量,主要问题是:
所以,虽然使用它并不是完全没有问题,但最佳方法不是使用它们,而是不时地碰到一个本地线程最简单的墙可能的解决方案,而不需要改变很多代码,你将不得不妥协,有一个不完美的面向对象模型与线程本地或更改相当多的代码来做同样的事情。
所以,这主要是考虑哪个问题对你的案例来说是最好的解决方案,如果你真的要沿着线程本地路径走下去,我肯定会建议你用那些记住的块做到这一点。完成后清理,如下所示:
around_filter :do_with_current_user
def do_with_current_user
Thread.current[:current_user] = self.current_user
begin
yield
ensure
Thread.current[:current_user] = nil
end
end
这确保在使用此线程之前,线程局部变量在被使用之前被清除。
答案 1 :(得分:21)
这个小宝石确保你的线程/请求局部变量不会在请求之间粘住:https://github.com/steveklabnik/request_store
答案 2 :(得分:7)
接受的答案涵盖了这个问题,但是Rails 5现在提供了一个使用Thread.current的“抽象超类”ActiveSupport::CurrentAttributes。
我想我会提供一个链接,作为可能的(unpopular)解决方案。
https://github.com/rails/rails/blob/master/activesupport/lib/active_support/current_attributes.rb
答案 3 :(得分:3)
接受的答案在技术上是准确的,但正如答案中温和地指出的那样,http://m.onkey.org/thread-safety-for-your-rails不是那么温和:
如果您不是必须使用线程本地存储<settings>
<mirrors>
<mirror>
<id>myId</id>
<name>MirrorName</name>
<url>http://url.com:8081/repositories</url>
<mirrorOf>*,!public-snapshots,!public-legacy,!sonar</mirrorOf>
</mirror>
</mirrors>
</settings>
request_store
的gem是另一个解决方案(更好),但只是阅读那里的自述文件,以了解更多原因,远离线程本地存储。
几乎总有一种更好的方式。