Рельсы, Когда я должен использовать строгие параметры?

#ruby-on-rails #strong-parameters

Вопрос:

Я не уверен, правильно ли я понимаю концепцию сильных параметров. Я должен использовать строгие параметры для параметров, которые я буду использовать только для редактирования некоторых данных? Или я должен использовать их для всех параметров, которые я хочу получить в контроллере? Например, я хочу получить данные между двумя датами, поэтому мне нужны даты 1 и 2 в качестве параметров. Должен ли я использовать здесь сильные парамы или нет?

Комментарии:

1. Строгие параметры используются для массового назначения , чтобы явно разрешить (или запретить) использование определенных атрибутов из более крупной структуры данных. Для отдельных атрибутов вы можете просто использовать params[:date1] . (здесь вы выражаетесь прямо)

2. Не могли бы вы привести какой-нибудь пример, чтобы помочь мне понять это?

3. guides.rubyonrails.org/…

Ответ №1:

Самый простой способ понять, когда следует использовать строгие параметры, — это понять, что такое массовое назначение. В Rails 3 вы можете сделать следующее:

 class CreateUsers < ActiveRecord::Migration[3.0]
  def change
    create_table :users do |t|
      t.string :email
      t.string :encrypted_password
      t.boolean :admin
      t.timestamps
    end
  end
end
 
 
class UserController < ApplicationController
  def create
    @user = User.new(params[:user])
    if @user.save
      redirect_to @user
    else
      render :new
    end
  end 
end

 

Здесь мы просто передаем «хэш» (на самом деле это экземпляр ActionController::Parameters) прямо в модель. Все, что злонамеренному пользователю нужно сделать здесь, — это запросить:

 POST /users?users[admin]=1 
 

И они создали учетную запись администратора. В 2012 году Егор Хомаков лихо воспользовался одной из таких лазеек в Github, чтобы совершить переход в репозиторий Rails.

Такую атаку тривиально выполнить с помощью cURL или с помощью веб-инспектора для управления формой.

Если мы внесем в белый список, какие атрибуты пользователь должен иметь возможность передавать:

 class UserController < ApplicationController
  def create
    @user = User.new(
      params.require(:user)
            .permit(:email, :password, :password_confirmation)
    )
    if @user.save
      redirect_to @user
    else
      render :new
    end
  end 
end
 

Тогда это позволяет избежать уязвимости — сильные параметры на самом деле являются простым DSL для нарезки и нарезки вложенных хэш-подобных структур. Что изменилось в Rail 4, так это то, что при передаче n экземпляра ActionController::Parameters модели возникает исключение, если вызов #permitted? объекта параметров не возвращает значение true. Это позволяет избежать возникновения уязвимости массового назначения просто из-за лени или невежества программиста.

Он не очищает ваши входные данные каким-либо другим способом. Например, это не предотвратит внедрение SQL или удаленное выполнение кода, если вы будете небрежно относиться к вводу данных пользователем.

Вам не нужны строгие параметры, если вы передаете параметры один за другим, как в этом очень надуманном примере:

 class UserController < ApplicationController
  def create
    @user = User.new do |u|
      u.email = params[:user][:email]
      u.password = params[:user][:password]
      u.password_confirmation = params[:user][:password_confirmation]
    end
    if @user.save
      redirect_to @user
    else
      render :new
    end
  end 
end
 

Комментарии:

1. Стоит отметить, что вы не должны на самом деле реализовывать свои сильные параметры так, как показано здесь. Код правильный, но лучше иметь частный [MODEL]_params метод в вашем контроллере (например user_params , article_params ), который вы можете вызывать из каждого метода в этом контроллере, которому требуется доступ к параметрам. Это облегчает привыкание использовать сильные параметры — редко бывает причина НЕ использовать сильные параметры, и вы узнаете об этом, когда столкнетесь с этим.

2. @JohnP пример написан для краткости. Однако извлечение ваших сильных параметров в метод на самом деле не имеет особых достоинств само по себе, за исключением того, что оно позволяет избежать дублирования. В этом примере нет дублирования, поэтому, следовательно, нет нарушения DRY.

3. @JohnP что касается части «это облегчает привыкание» — это бессмысленно, так как rails вызовет исключение, если вы этого не сделаете.

4. @макс, спасибо, чувак!

5. @max Rails не вызовет исключения, если вы params получите прямой доступ. Настройка частного user_params метода или чего — либо еще по умолчанию и использование его повсюду, таким образом, является просто разумным советом ISTM-в какой-то момент вы почти всегда будете получать доступ к параметрам в методах вашего контроллера! Конечно, в кратком примере нет дублирования, но если мы пытаемся помочь людям, то предложить лучшие практики было бы разумно. (Я не собирался критиковать ваш ответ — как я уже сказал, он правильный — просто улучшение.)