Reputation: 4755
rails new blah
cd blah
rails g model user password_digest:string
rake db:migrate
app/models/user.rb
class User
has_secure_password
end
(and last step is enable bcrypt-ruby in Gemfile then bundle install)
So now we have a blank rails 4.0 setup with a user that has a secure password. Lets see how the validation works (if we run rails c
and try some stuff out):
User.new.valid?
=> false
# good
User.new(:password => "k").valid?
=> false
# good - needs confirmation
user = User.new(:password => "k", :password_confirmation => "k")
=> #<User id: nil, password_digest: "$2a$10$csB375UE7yWANd1I0SJqf.UqwL/5URr8lyjCKebn3FXf...", created_at: nil, updated_at: nil>
# good - it hashed our password perfectly
user.valid?
=> true
# good - exactly how it should work
user = User.new(:password => "k", :password_digest => "owned", :password_confirmation => "k")
=> #<User id: nil, password_digest: "owned", created_at: nil, updated_at: nil>
# I just directly specified the digest... that shouldn't be possible?
user.valid?
=> true
# bad.. very bad... they just let us change it directly!
Can you see what happened? Look at the last test, we set the password and confirmation properly - that's why it's valid. But we also set the password digest directly which wrote over the password and confirmation we provided and allowed me to directly modify the value... and that user REMAINED VALID :(
What security measures are in place to prevent direct modification of the password_digest? Setting it should either have no effect or should make that user object invalid.
PS: If anybody knows better tags, please edit :D
Upvotes: 0
Views: 95
Reputation: 29399
The approach of using strong parameters moves the security from the model to the controller on the grounds that you can't access the model except through the controller. By design, there are no protections at the model level in terms of what parameters can be passed.
Upvotes: 2