2

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)ますが、攻撃者が任意の値を任意のフィールドに割り当てるように招待しているようです。これは問題ですか?何人かのコメント投稿者が同様の質問をしましたが、回答はありませんでした。

4

2 に答える 2

3

sendメソッドを動的に呼び出す一般的な方法です (何を呼び出すかが事前にわからない場合)。

セキュリティが心配な場合は、必ずいくつかの検証を行う必要があります。簡単な制限チェックを次に示します。

def initialize(attributes = {})
  attributes.each do |name, value|
    if [:name, :email, :content].include?(name)
      send("#{name}=", value)
    end
  end
end
于 2012-06-27T14:52:03.400 に答える
1

最近、同じ RailsCastについて質問したところ、初期化子が危険だと言われましたが、残念ながら正当な理由は示されませんでした。

もう少し深く掘り下げた結果、jdoe があなたの質問に対するコメントで回避した理由により、この方法はセキュリティ上の弱点をもたらさないと私は信じています。send メソッドはアクセサ メソッドを回避しないため、属性のセキュリティは通常どおりアクセサ宣言によって制御されます。

ただし、アクセスできない、または存在しない属性を割り当てようとする試みに対する堅牢性を向上させるために、検証チェックをお勧めします。Sergioの提案に似ていますが、より一般的です:

attributes.each do |name, value|
  send("#{name}=", value) if respond_to?("#{name}=")
end
于 2013-06-13T12:42:33.627 に答える