Login form


#1

I have a model for user and login page. When I enter right username and
password, i can not login to the system altough the user exists in the
db.

here’s the model:

require ‘digest/sha2’
class User < ActiveRecord::Base
attr_accessor :password

def password=(pass)
salt = [Array.new(6){rand(256).chr}.join].pack(“m”).chomp
self.password_salt, self.password_hash = salt,
Digest::SHA256.hexdigest(pass + salt)
end

def self.authenticate(username, password)
user = User.find(:first, :conditions => [‘username = ?’, username])
if user.blank? || Digest::SHA256.hexdigest(password +
user.password_salt) != user.password_hash
raise “Username or password invalid”
end
user
end
end

when i test the authenticate method from the console, when i type the
right username and password it doesn’t raise error. but when i try to
login from the login page it raise the error.

my view is:
<%= flash[:notice] -%>
<% form_tag :controller => :user, :action => :login do %>



Username
<%= text_field 'user', 'username' %>

Password
<%= password_field 'user', 'password' %>


<%= submit_tag 'Login' -%> <% end %>

and my controller is:

class UserController < ApplicationController

def login
if request.post?
begin
session[:user] =
User.authenticate(params[:username],params[:password]).id
redirect_to :controller => session[:intended_controller],
:action => session[:intended_action]
rescue
flash[:notice] = “Username or password invalid”
end
end
end

def logout
session[:user] = nil
redirect_to :controller => :user, :action => :index
end

def register
if request.post?
@user = User.new(params[:user])
if @user.save
redirect_to :action => :account_creation_success, :id => @user
end
end
end

end

do i forget something?


#2

I think the problem is in the view. Check to see of the params that
come out of that form don’t look like 'params[:user][:username] ’ and
’ params[:user][:password] ’

This scheme was inspired by Fowler’s Rails Recipes, right? I really
like that basic scheme, but I’ve used a modifed version that lets you
validate_confirmation_of :password almost for free. Look:

require ‘digest/sha2’
class User < ActiveRecord::Base

validates_uniqueness_of :name, :on => :save, :message => “already in
use”
validates_confirmation_of :password, :on => :save, :message => “should
match confirmation”

before_save :encrypt_password

attr_accessor :password, :password_confirmation # virtual attributes
needed to validate confirmation of password

def encrypt_password

Renamed from password=(pass). Which was causing bad behaviour when

working through associations.

Note the change to self.password from pass in the assignment line

call with a before_save callback

salt= [Array.new(6) {rand(256).chr}.join].pack(“m”).chomp
self.password_salt, self.password_hash = salt,
Digest::SHA256.hexdigest(self.password+salt)
end

def self.authenticate(username, password)
user = User.find(:first, :conditions=>[‘name = ?’, username])
if user.blank?
raise “No Such User.”
elsif Digest::SHA256.hexdigest(password + user.password_salt) !=
user.password_hash
raise “Bad Password.”
else
user
end
end

end


#3

I think the problem is in the view. Check to see of the params that
come out of that form don’t look like 'params[:user][:username] ’ and
’ params[:user][:password] ’

This scheme was inspired by Fowler’s Rails Recipes, right? I really
like that basic scheme, but I’ve used a modifed version that lets you
validate_confirmation_of :password almost for free. Look:

require ‘digest/sha2’
class User < ActiveRecord::Base

validates_uniqueness_of :name, :on => :save, :message => “already in
use”
validates_confirmation_of :password, :on => :save, :message => “should
match confirmation”

before_save :encrypt_password

attr_accessor :password, :password_confirmation # virtual attributes
needed to validate confirmation of password

def encrypt_password

Renamed from password=(pass). Which was causing bad behaviour when

working through associations.

Note the change to self.password from pass in the assignment line

call with a before_save callback

salt= [Array.new(6) {rand(256).chr}.join].pack(“m”).chomp
self.password_salt, self.password_hash = salt,
Digest::SHA256.hexdigest(self.password+salt)
end

def self.authenticate(username, password)
user = User.find(:first, :conditions=>[‘name = ?’, username])
if user.blank?
raise “No Such User.”
elsif Digest::SHA256.hexdigest(password + user.password_salt) !=
user.password_hash
raise “Bad Password.”
else
user
end
end

end


#4

Oops!

that callback should be before_create not before save.