在RailsCast 219中,提供了以下代码,用于创建从表单来回传送数据的类,但没有任何ActiveRecord持久性:
class Message
include ActiveModel::Validations
attr_accessor :name, :email, :content
validates_presence_of :name
validates_format_of :email, :with => /^[-a-z0-9_+\.]+\@([-a-z0-9]+\.)+[a-z0-9]{2,4}$/i
validates_length_of :content, :maximum => 500
def initialize(attributes = {})
attributes.each do |name, value|
send("#{name}=", value)
end
end
end
我是Ruby新手,但send("#{name}=", value)
似乎是攻击者的邀请
将任意值分配给任意字段。这是一个问题吗?一些评论者问similar questions,但没有回复。
答案 0 :(得分:3)
send
是动态调用方法的常用方法(当您事先不知道要调用的内容时)。
如果您担心安全性,那么您一定要做一些验证。这是一个简单的限制性检查:
def initialize(attributes = {})
attributes.each do |name, value|
if [:name, :email, :content].include?(name)
send("#{name}=", value)
end
end
end
答案 1 :(得分:1)
当我最近询问question与相同的RailsCast相关时,并被告知初始化程序很危险,但遗憾的是没有给出任何理由。
深入研究后,我现在相信方法没有引入任何安全漏洞,因为jdoe在他对你的问题的评论中没有提到。 send方法不会绕过访问器方法,因此属性的安全性由访问器声明控制正常。
但是,我建议进行验证检查,以提高针对尝试分配不可访问或不存在的属性的稳健性。类似于塞尔吉奥的建议,但更为笼统:
attributes.each do |name, value|
send("#{name}=", value) if respond_to?("#{name}=")
end