我有一个多态路由,它接受ActiveRecord模型的名称(例如"User"
,"UserGroup"
)作为参数。
如何基于参数安全地访问类?
简单的实现(可能不安全)是:
model_class = params[:modelName].constantize
如何在不造成漏洞的情况下实现这一点?
我将使用一个显式的允许用户在此上下文中常量化的模型allowlist:
allowed_classes = ["User", "UserGroup"]
class_name = params[:modelName].presence_in(allowed_classes)
if class_name.present?
model_class = class_name.safe_constantize
else
# handle error
end
presence_in
返回数组中包含的字符串,nil
返回数组中不包含的字符串。
我想说,您需要对该参数进行验证,检查其值是否在可接受的模型集合中,然后,确实使用.constantize
。如果您接受所有模型,并且所有模型都继承自ApplicationRecord或其他东西,那么您可以像这样生成集合:
ApplicationRecord.subclasses.collect { |type| type.name }.sort
并检查params[:modelName]是否在此集合中。
还请注意,如果不存在与结果匹配的常量,constantize
会抛出错误:
[1] pry(main)> "NotAConstant".constantize
NameError: uninitialized constant NotAConstant