
#2 User Authentication
在不使用任何现成Authentication gem的前提下,建立一个简单灵活的用户验证机制。本期内容是基于第一期Blog例子。
Create User migration:
db/migrate/20111214073443_create_users.rb
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :login
t.string :hashed_password
t.string :salt
t.timestamps
end
end
end
class CreateUsers < ActiveRecord::Migration def change create_table :users do |t| t.string :login t.string :hashed_password t.string :salt t.timestamps end end end
User 模型:
app/models/user.rb
class User < ActiveRecord::Base
validates :login, :presence => true
def password
@password
end
def password=(pass)
return unless pass
@password = pass
generate_password(pass)
end
# 此处用动词形式(authenticate)更加合适, 特此说明一下. 感谢 Chen Kai 同学的提醒.
def self.authentication(login, password)
user = User.find_by_login(login)
if user && Digest::SHA256.hexdigest(password + user.salt) == user.hashed_password
return user
end
false
end
private
def generate_password(pass)
salt = Array.new(10){rand(1024).to_s(36)}.join
self.salt, self.hashed_password =
salt, Digest::SHA256.hexdigest(pass + salt)
end
end
class User < ActiveRecord::Base validates :login, :presence => true def password @password end def password=(pass) return unless pass @password = pass generate_password(pass) end # 此处用动词形式(authenticate)更加合适, 特此说明一下. 感谢 Chen Kai 同学的提醒. def self.authentication(login, password) user = User.find_by_login(login) if user && Digest::SHA256.hexdigest(password + user.salt) == user.hashed_password return user end false end private def generate_password(pass) salt = Array.new(10){rand(1024).to_s(36)}.join self.salt, self.hashed_password = salt, Digest::SHA256.hexdigest(pass + salt) end end
Sessions 控制器:
app/controllers/sessions_controller.rb
class SessionsController < ApplicationController
def new
end
def create
@user = User.authentication(params[:login], params[:password])
if @user
session[:user_id] = @user.id
flash[:notice] = "Weclome #{@user.login}"
redirect_to posts_path
else
flash[:notice] = "The login or password is not correct."
redirect_to new_session_path
end
end
end
class SessionsController < ApplicationController def new end def create @user = User.authentication(params[:login], params[:password]) if @user session[:user_id] = @user.id flash[:notice] = "Weclome #{@user.login}" redirect_to posts_path else flash[:notice] = "The login or password is not correct." redirect_to new_session_path end end end
登陆页面
app/views/sessions/new.html.erb
<h1>Admin Login</h1>
<%= form_tag sessions_path do -%>
<label for="login">Login</label>
<%= text_field_tag :login, params[:login] %>
<label for="password">Password</label>
<%= password_field_tag :password, params[:password] %>
<%= submit_tag "Login"%>
<% end %>
<h1>Admin Login</h1> <%= form_tag sessions_path do -%> <label for="login">Login</label> <%= text_field_tag :login, params[:login] %> <label for="password">Password</label> <%= password_field_tag :password, params[:password] %> <%= submit_tag "Login"%> <% end %>