fgu*_*len 11 ruby-on-rails classloader deserialization
尝试使用YAML.load或Marshal.load生成损坏的对象反序列化一个非常简单的对象,因为在反序列化过程中不需要属于的类.
例:
# app/models/my_model.rb
class MyModel
attr_accessor :id
end
# test/unit/serializing_test.rb
require 'test_helper'
class SerializingTest < Test::Unit::TestCase
def test_yaml_serialize_structure
my_model = MyModel.new
my_model.id = 'my model'
File.open( "#{Rails.root}/tmp/object.yml" , 'w' ) do |f|
YAML::dump(my_model, f)
end
end
def test_yaml_deserialize_structure
object = YAML.load_file "#{Rails.root}/tmp/object.yml"
assert( object.instance_of? MyModel )
assert_equal( 'my model', object.id )
end
end
Run Code Online (Sandbox Code Playgroud)
使用此代码,我们可以运行此shell控制台会话而不会出现任何错误
$ ruby -Itest test/unit/serializing_test.rb -n test_yaml_serialize_structure
$ ruby -Itest test/unit/serializing_test.rb -n test_yaml_deserialize_structure
Run Code Online (Sandbox Code Playgroud)
但是如果我从Rails控制台运行反序列化调用,则对象不会被正确反序列化,因为该类永远不需要:
$ rails c
ruby-1.9.2-p0 > object = YAML.load_file "#{Rails.root}/tmp/object.yml"
=> #<Syck::Object:0x0000010322ea30 @class="MyModel", @ivars={"id"=>"my model"}>
Run Code Online (Sandbox Code Playgroud)
我知道唯一的问题是这个课程不是必需的,因为如果我需要手工,一切都有效:
ruby-1.9.2-p0 > require "#{Rails.root}/app/models/my_model"
=> ["MyModel"]
ruby-1.9.2-p0 > object = YAML.load_file "#{Rails.root}/tmp/object.yml"
=> #<MyModel:0x0000010320c8e0 @id="my model">
Run Code Online (Sandbox Code Playgroud)
我只提供了YAML的例子,但Marshal是相同的.
还要说虽然我在Rails控制台中重现了这个问题,但这个问题让我对我的应用程序的正常请求感到疯狂.
所以问题是:如何在Rails中反序列化对象而不必手动需要所有类?
谢谢
F.
fgu*_*len 21
好吧,在阅读了@tadman和我在西班牙语邮件列表[1]中收到的一堆答案后,我已经收集了一些热门提示,当你必须处理Rails中的Ruby反序列化和类加载时:
超快的解决方案
config.cache_classes = true在你的使用,development.rb但你会丢失类自动刷新.
好的解决方案
要求所有被会被反序列化,但类不是require,但与require_dependency[2]因此,在开发环境中的类自动刷新将继续工作.
优雅的解决方
对YAML和Marshal gem进行修补,告诉他们require_dependency在找到一个未定义的类进行反序列化时调用.
并且@Xavi已经给我发了一个猴子补丁的提议Marshal(他说他在空中写了它并且没有经过测试所以请自行使用它)[3]
| 归档时间: |
|
| 查看次数: |
4459 次 |
| 最近记录: |