Rails使用Symbol vs String作为params散列中的键
如果我们使用一个字符串作为哈希键,Ruby需要计算字符串并查看它的内容(并计算它的哈希函数),并将结果与已存储在哈希中的键的(散列)值进行比较。
如果我们使用一个符号作为哈希键,它隐含着它是不可变的,所以Ruby可以基本上只是比较object-id的(哈希函数)和已经存储在(哈希)对象的哈希。 (快多了)。
但是,Rails params
是HashWithIndifferentAccess
实例,如果我们编写params[:some_key]
它将:some_key
转换为'some_key'
,然后尝试在params散列中查找密钥。 第159行
def convert_key(key)
key.kind_of?(Symbol) ? key.to_s : key
end
所以如果查找速度很慢并且String作为Hash中的键,为什么HashWithIndifferentAccess
会将符号键转换为字符串。
原因以前是安全。 它在Ruby 2.2或更高版本中不再重要。
Ruby 2.2符号未被垃圾收集之前。 这意味着一旦符号通过文字( :my_symbol
)或#to_sym
它就会永远存在。
如果Rails使用符号而不是字符串,那么它会在请求中创建对应于参数名称的符号。 攻击者可以通过使应用程序分配数十万个符号来发送名为param1
, param2
,...和排气服务器内存的参数。
在Ruby 2.2或更高版本中不再是这种情况
:symbol.to_s
将始终创建一个新的实例字符串,而"string".to_sym
将始终生成相同的符号。
p "string".to_sym.object_id
#=> 272028
p "string".to_sym.object_id
#=> 272028
p :symbol.to_sym.to_s.object_id
#=>70127441809260
p :symbol.to_sym.to_s.object_id
#=>70127441809160
因此,类的设计者似乎将键存储为字符串以避免在访问期间不必要地创建字符串,特别是在使用hash.keys
方法(它将键返回为字符串)的情况下。
上一篇: Rails using Symbol vs String as key in params hash
下一篇: How can I make UINavigationController transparent in one view controller only?