Advanced Rails - Building Industrial-Strength Web Apps in Record Time

(Tuis.) #1

130 | Chapter 5: Security


TheUsermodel has a virtual attribute for the unencrypted password, so that you can
set the password using the instance methodUser#password=and it will be hashed
automatically. The hashing is performed by abefore_save callback:


class User < ActiveRecord::Base
attr_accessor :password

before_save :encrypt_password

protected

def encrypt_password
return if password.blank?
self.salt = Digest::SHA1.hexdigest("--#{Time.now.to_s}--#{login}--") if
new_record?
self.crypted_password = encrypt(password)
end

def encrypt(password)
Digest::SHA1.hexdigest("--#{salt}--#{password}--")
end
end

The actual authentication is handled by theUser.authenticateclass method, which
takes a login and password and returns either the corresponding user ornilif the
login or password are incorrect.


class User < ActiveRecord::Base
def self.authenticate(login, password)
u = find_by_login(login)
u && u.authenticated?(password)? u : nil
end

def authenticated?(password)
crypted_password == encrypt(password)
end
end

Don’t Trust the Client


ActionPack (ActionController plus ActionView) makes a lot of things easier for you
as a developer. To do so, it abstracts away a lot of the details of the HTT Prequest/
response cycle. This is usually a good thing: you really don’t want to deal with every
detail of the CGI protocol. But it is important not to let this abstraction get in the
way of writing secure code. One of the foundational principles that you should keep
in mind is that you can never trust the information that the web browser (the client)
sends you.


This is one area where the leaky abstraction that Rails provides can hurt. It really
pays to understand how HTT Pworks, at least to the point that you know whether a
particular piece of information comes from the client, the application framework, or

Free download pdf