#ruby-on-rails #strong-parameters
Вопрос:
Я не уверен, правильно ли я понимаю концепцию сильных параметров. Я должен использовать строгие параметры для параметров, которые я буду использовать только для редактирования некоторых данных? Или я должен использовать их для всех параметров, которые я хочу получить в контроллере? Например, я хочу получить данные между двумя датами, поэтому мне нужны даты 1 и 2 в качестве параметров. Должен ли я использовать здесь сильные парамы или нет?
Комментарии:
1. Строгие параметры используются для массового назначения , чтобы явно разрешить (или запретить) использование определенных атрибутов из более крупной структуры данных. Для отдельных атрибутов вы можете просто использовать
params[:date1]
. (здесь вы выражаетесь прямо)2. Не могли бы вы привести какой-нибудь пример, чтобы помочь мне понять это?
Ответ №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-в какой-то момент вы почти всегда будете получать доступ к параметрам в методах вашего контроллера! Конечно, в кратком примере нет дублирования, но если мы пытаемся помочь людям, то предложить лучшие практики было бы разумно. (Я не собирался критиковать ваш ответ — как я уже сказал, он правильный — просто улучшение.)