【问题标题】:Rails 4 parameters; how to whitelist a param to a set of valuesRails 4 参数;如何将参数列入一组值的白名单
【发布时间】:2017-08-02 18:52:57
【问题描述】:

我已经阅读了一些帖子,例如Value whitelist using strong parameters in Rails 4,但这并不是我所需要的。

我有一个控制器,它接受一个 ID 并加载一个模型。它还可以选择接受一个查询字符串参数 (style),它可以是三个值之一,small、medium 或 large。这被传递给模型上的一个方法,该方法使用它来获取附加图像(使用回形针)。我注意到如果我传递了一个无效的参数(例如style=wibble),那么我会收到一个 400 错误并通知内部文件路径不存在。 Brakeman 还指出这是一个安全问题...

def show
  style = params[:style] || :medium

  thing = Model.find(params[:id])

  path = "#{Rails.root}/public#{thing.image_url(style)}"
  content_type = thing.image.content_type || 'image/png'
  send_file path, type: content_type, disposition: 'inline'
end

我们在其他地方使用ActionController Parameters 效果很好;但我看不出如何将参数选项“列入白名单”?我所见过的所有地方都说要使用模型验证器,但这是假设我正在提交一个参数来更新模型,而我不是。

我知道我可以这样做:

return head :not_found unless %w(small medium large).include? style

这是最好的方法吗?

【问题讨论】:

    标签: ruby-on-rails ruby validation security controllers


    【解决方案1】:

    我为此目的编写了一个扩展 ActionController::Parameters 的 gem:将参数值列入白名单。它简单轻巧。你可以这样使用它:

    def model_params
      params.require(:model).permit(:style, :other_attribute).allow(style: %w[small medium large])
    end
    

    希望对你有用

    https://github.com/msimonborg/allowable

    【讨论】:

    • @Nick 谢谢! :)
    • @m.simonborg 干得好!虽然,我不认为 { 'a' => 1 }.allow(a: 1) 应该工作,但您的代码忽略了哈希是常规哈希或 HashWithIndiffergentAccess 的事实。此外,{ a: 1, 'a' => 2 }.allow(a: [1,2]) 将允许两个键,我无法根据键的类型来限制它。 (我没有测试过,只是看源码)
    • @MrYoshiji 谢谢,这是非常好的反馈。我开发它时考虑到了ActionController::Parameters,因此它的实现可能不是Hash 的最佳实现。我认为在单独的模块中单独实现 Hash 将解决这些有效问题
    • @MrYoshiji 再次感谢您提出问题,推动了这些更改,以便在Hash中尊重关键类型
    • @m.simonborg 感谢您提供这个工具,我可能会在下一个项目中使用它!
    【解决方案2】:

    首先,您需要定义一个将所有有效style 值列入白名单的常量(我认为size_type 是一个更明确的名称)。 (注意符号/字符串比较)。

    然后,如果 params[:style] 未包含在白名单值中,则返回 404,或者退回到 'medium':

    style = Model::AVAILABLE_SIZE_TYPES.include?(params[:style]) ? params[:style] || Model::AVAILABLE_SIZE_TYPES.first
    

    就我个人而言,我不喜欢用户输入的后备。他们做错了什么(操纵 URL、更改表单中的值等),他们应该得到一个错误页面。

    我暗示常量是在模型中定义的,但它不应该存在,因为它与业务逻辑无关,但与模型的显示有关。如果您有 ModelDecorator,请在此处定义它。

    【讨论】:

    • 随之而来的是,looks like 使用回形针,模型可能设置为 has_attached_file :avatar, styles: { thumb: ["32x32#", :png] },所以我可能建议在那里也使用常量 AVAILABLE_SIZE_TYPES = { thumb: ["32x32#", :png] } has_attached_file :avatar, styles: AVAILABLE_SIZE_TYPES 然后 @987654331 @(再次注意字符串/符号)...单一事实来源...如果您稍后添加:tiny,它已经更新了。
    • 扩展@SimpleLime 所说的:你可以有一个常量,比如IMAGE_CONFIGURATIONS = { small: ['32x32#', :png] }.freeze,然后定义AVAILABLE_SIZE_TYPES = IMAGE_CONFIGURATIONS.keys,甚至有一个ImageConfiguration 对象(参见下面的“提取值对象”部分优秀文章toptal.com/ruby-on-rails/decoupling-rails-components)
    猜你喜欢
    • 2015-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多