对于在 Thread.current 哈希中存储信息(例如,current_user、当前子域等)的做法,我不断收到相互矛盾的意见。该技术被提议作为一种简化模型层内后续处理(查询范围、审核等)的方法。
许多人认为这种做法不可接受,因为它破坏了 MVC 模式。
其他人对该方法的可靠性/安全性表示担忧,我的由两部分组成的问题集中在后一个方面。
-
Thread.current
哈希值是否保证在其整个周期内对一个且仅一个响应可用且私有?
-
据我了解,线程在响应结束时很可能会被移交给其他传入请求,从而泄漏 Thread.current 中存储的任何信息。在响应结束之前清除此类信息(例如,通过从控制器的 after_filter
执行 Thread.current[:user] = nil
)足以防止此类安全漏洞吗?< /p>
谢谢!
朱塞佩
I keep getting conflicting opinions on the practice of storing information in the Thread.current
hash (e.g., the current_user, the current subdomain, etc.). The technique has been proposed as a way to simplify later processing within the model layer (query scoping, auditing, etc.).
Many consider the practice unacceptable because it breaks the MVC pattern.
Others express concerns about reliability/safety of the approach, and my 2-part question focuses on the latter aspect.
-
Is the Thread.current
hash guaranteed to be available and private to one and only one response, throughout its entire cycle?
-
I understand that a thread, at the end of a response, may well be handed over to other incoming requests, thereby leaking any information stored in Thread.current
. Would clearing such information before the end of the response (e.g. by executing Thread.current[:user] = nil
from a controller's after_filter
) suffice in preventing such security breach?
Thanks!
Giuseppe
发布评论
评论(4)
没有特定的理由远离线程局部变量,主要问题是:
因此,虽然它并不是完全不可能使用,但最好的方法是不使用它们,但时不时你会遇到线程本地化的问题将是最简单的解决方案,无需进行大量更改代码,你将不得不妥协,有一个不太完美的面向对象模型与线程本地或改变相当多的代码来做同样的事情。
因此,这主要是一个思考问题,哪个将是适合您的情况的最佳解决方案,如果您真的要走线程本地路径,我肯定会建议您使用记住在之后清理的块来执行此操作它们已完成,如下所示:
如果该线程被回收,这可确保线程局部变量在使用之前被清理。
There is not an specific reason to stay away from thread-local variables, the main issues are:
So, while it's not completely out of question to use, the best approach is not to use them, but from time to time you hit a wall where a thread local is going to be the simplest possible solution without changing quite a lot of code and you will have to compromise, have a less than perfect object oriented model with the thread local or changing quite a lot of code to do the same.
So, it's mostly a matter of thinking which is going to be the best solution for your case and if you're really going down the thread-local path, I'd surely advise you to do it with blocks that remember to clean up after they are done, like the following:
This ensures the thread local variable is cleaned up before being used if this thread is recycled.
这个小宝石确保您的线程/请求局部变量不会粘在请求之间: https://github.com/steveklabnik/request_store< /a>
This little gem ensures your thread/request local variables not stick between requests: https://github.com/steveklabnik/request_store
接受的答案涵盖了这个问题,但Rails 5现在提供了一个“抽象超类”ActiveSupport::CurrentAttributes 使用 Thread.current。
我想我会提供一个链接作为可能的(不受欢迎)解决方案。
https://github.com/rails/rails/blob /master/activesupport/lib/active_support/current_attributes.rb
The accepted answer covers the question but as Rails 5 now provides a "Abstract super class" ActiveSupport::CurrentAttributes which uses Thread.current.
I thought I would provide a link to that as a possible(unpopular) solution.
https://github.com/rails/rails/blob/master/activesupport/lib/active_support/current_attributes.rb
接受的答案在技术上是准确的,但正如答案中温和指出的那样,以及 http ://m.onkey.org/thread-safety-for-your-rails 不太温和:
不要使用线程本地存储,
Thread.current
如果你不这样做绝对不必request_store
是另一个解决方案(更好),但只需阅读自述文件即可了解更多留下来的理由远离线程本地存储。几乎总有更好的方法。
The accepted answer is technically accurate, but as pointed out in the answer gently, and in http://m.onkey.org/thread-safety-for-your-rails not so gently:
Don't use thread local storage,
Thread.current
if you don't absolutely have toThe gem for
request_store
is another solution (better) but just read the readme there for more reasons to stay away from thread local storage.There is almost always a better way.