Home > Software engineering >  Rails When should I use strong parameters?
Rails When should I use strong parameters?

Time:10-13

I am not sure if I understand the concept of strong parameters correctly. I should use strong parameters to params that I will use only to edit some data? Or I should use them for every params I want to get in controller? For example I want to get data between two dates, so I need date1 and date2 as params. Should I use here strong params or not?

CodePudding user response:

The easiest way to understand when you should use strong parameters is to understand what a mass assignment volunerability is. In Rails 3 you could do the following:

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

Here we are just passing a "hash" (its actually an ActionController::Parameters instance) straight into the model. All a malicous user has to do here is request:

POST /users?users[admin]=1 

And they have created an admin account. In 2012 Egor Homakov famously exploited one such loophole in Github to commit to the Rails repository.

Such an attack is trivial to perform with cURL or by using the web inspector to manipulate a form.

If we whitelist which attributes the user should be able to pass:

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

Then this avoids the vulnerability - strong parameters is really just a simple DSL for slicing and dicing nested hash like structures. What changed in Rail 4 is that when you pass a n instance of ActionController::Parameters to a model an exception is raised unless calling #permitted? on the parameters object returns true. This avoids a mass assignment vulnerability from occuring simply due to programmer laziness or ignorance.

It does not sanitize your inputs in any other way. Like for example it won't prevent SQL injection or remote code execution if you treat user input carelessly.

You don't need strong parameters if you're passing parameters one by one like in this very contrived example:

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
  • Related