Jon*_*aun 20 security shared-nothing ruby-on-rails class-variables
PHP在无共享环境中运行,在这种情况下,这意味着每个Web请求都在一个干净的环境中运行.除了通过单独的持久层(文件系统,数据库等)之外,您无法访问其他请求的数据.
Ruby on Rails怎么样?我刚看了一篇博文,说明单独的请求可能会访问同一个类变量.
我想到这可能取决于Web服务器. Mongrel的FAQ说明Mongrel每个请求使用一个线程 - 建议无共享环境.FAQ继续说RoR不是线程安全的,这进一步表明RoR不会存在于共享环境中,除非新请求重用从先前请求创建的内存中对象.
显然这具有巨大的安全后果.所以我有两个问题:
更新:我会进一步澄清. 在Java servlet容器中,您可以拥有跨多个请求持久化的对象.这通常用于缓存多个用户可以访问的数据,数据库连接等.在PHP中,这不能在应用程序层完成,它必须在像Memcached这样的单独的持久层中完成.因此,双重问题是:哪种情况是RoR(PHP或Java),如果像Java一样,哪些数据类型在多个请求中持续存在?
mol*_*olf 31
简而言之:
版本较长:
Rails进程通过加载框架和应用程序来开始其生命周期.它们通常只运行一个线程,它将在其生命周期内处理许多请求.因此,将严格按顺序发送请求.
尽管如此,所有类仍然存在于请求中.这意味着将从您的类和元类引用的任何对象(例如类变量和类实例变量)将在请求之间共享.例如,如果您尝试在类方法中记住methods(),期望它只会在当前请求期间保持不变,这可能会让您感到困惑.实际上,计算仅在第一次请求时执行.@var ||= expensive_calculation
从表面上看,实现缓存或依赖于跨请求持久性的其他行为似乎很不错.通常,它不是.这是因为大多数部署策略将使用多个 Rails进程来抵消它们自己的单线程特性.在等待慢速数据库查询时阻塞所有请求根本不是很酷,因此最简单的方法是生成更多进程.当然,这些过程并不共享任何东西(除了一些内存,你可能不会注意到).如果您在请求期间保存类变量或类实例变量中的内容,这可能会让您感到困惑.然后,不知何故,有时候东西似乎存在,有时它似乎消失了.(实际上,当然,数据在某些过程中可能存在也可能不存在,而在其他过程中则不存在).
一些部署配置(最显着的JRuby + Glassfish的)是实际上多线程.Rails是线程安全的,所以它可以处理它.但您的应用程序可能不是线程安全的.每次请求后都会抛弃所有控制器实例,但正如我们所知,这些类是共享的.如果您在类变量或类实例变量中传递信息,这可能会让您感到困惑.如果你没有正确使用同步方法,你很可能最终处于竞争状态地狱.
作为旁注:Rails通常在单线程进程中运行,因为Ruby的线程实现很糟糕.幸运的是,Ruby 1.9中的情况要好一些.和很多 JRuby中更好.
随着这些Ruby实现越来越受欢迎,似乎多线程Rails部署策略也将获得普及和数量.最好在编写具有多线程请求调度的应用程序时考虑到这一点.
这是一个相对简单的示例,说明了如果您不小心修改共享对象会发生什么.
创建一个新的Rails项目: rails test
创建一个新文件lib/misc.rb并输入:
class Misc
@xxx = 'Hello'
def Misc.contents()
return @xxx
end
end
Run Code Online (Sandbox Code Playgroud)ruby script/generate controller Posts index更改app/views/posts/index.html.erb以包含此代码:
<%
require 'misc'; y = Misc.contents() ; y << ' (goodbye) '
%>
<pre><%= y %></pre>
Run Code Online (Sandbox Code Playgroud)
(这是我们修改隐式共享对象的地方.)
config/routes.rb.ruby script/server并/posts多次加载页面.您将看到( goodbye)每个连续页面重新加载时字符串的数量增加1.| 归档时间: |
|
| 查看次数: |
5310 次 |
| 最近记录: |