= 使用 authlogic 做登录验证
== 在Gemfile中添加authlogic相关的gems
gem 'authlogic'
gem 'rails3-generators'
gem 'dynamic_form'
== 本地安装gems
gem install -l --no-ri --no-rdoc authlogic-2.1.6.gem
== 执行 bundle install 或者 bundle update.
== 创建UserSession
rails g authlogic:session UserSession
create app/models/user_session.rb
invoke test_unit
create test/unit/user_session_test.rb
create test/fixtures/user_sessions.yml
== 修正错误
* 在UserSession添加代码
app/models/user_session.rb
class UserSession < Authlogic::Session::Base
def to_key
new_record? ? nil : [ self.send(self.class.primary_key) ]
end
end
== 创建用户模型 User model
rails g model User
invoke active_record
create db/migrate/20110116013856_create_users.rb
conflict app/models/user.rb
Overwrite app/models/user.rb? (enter "h" for help) [Ynaqdh] y
force app/models/user.rb
invoke test_unit
create test/unit/user_test.rb
create test/fixtures/users.yml
== 创建角色模型 Role model
rails g model Role
invoke active_record
create db/migrate/20110116042653_create_roles.rb
conflict app/models/role.rb
Overwrite app/models/role.rb? (enter "h" for help) [Ynaqdh] y
force app/models/role.rb
invoke test_unit
create test/unit/role_test.rb
create test/fixtures/roles.yml
== 修改 CreateUsers migration
db/migrate/20110116013856_create_users.rb
class CreateUsers < ActiveRecord::Migration
def self.up
create_table :users do |t|
t.string :login, :null => false
t.integer :role_id, :null => false
t.string :email, :null => false
t.string :crypted_password, :null => false
t.string :password_salt, :null => false
t.string :persistence_token, :null => false
t.string :single_access_token, :null => false # optional, see Authlogic::Session::Params
t.string :perishable_token, :null => false # optional, see Authlogic::Session::Perishability
# magic fields (all optional, see Authlogic::Session::MagicColumns)
t.integer :login_count, :null => false, :default => 0
t.integer :failed_login_count, :null => false, :default => 0
t.datetime :last_request_at
t.datetime :current_login_at
t.datetime :last_login_at
t.string :current_login_ip
t.string :last_login_ip
t.timestamps
end
add_index :users, ["login"], :name => "index_users_on_login", :unique => true
add_index :users, ["email"], :name => "index_users_on_email", :unique => true
add_index :users, ["persistence_token"], :name => "idx_users_persistence", :unique => true
end
#User.create(:login => 'admin', :password => 'admin', :password_confirmation => 'admin', :role_id => 1)
def self.down
drop_table :users
end
end
* Persistence token: 是authlogic的持久性标记,将会存储在浏览器的Cookie中,远远比将用户id存在Cookie中安全。
* Perishable token: 用于审核或者重新设置密码
== 修改 CreateRoles migration
db/migrate/20110116042653_create_roles.rb
class CreateRoles < ActiveRecord::Migration
def self.up
create_table :roles do |t|
t.string :name
t.timestamps
end
Role.create(:name => 'administrator')
end
def self.down
drop_table :roles
end
end
== 执行创建表
rake db:migrate
== 修改User model
app/models/user.rb
class User < ActiveRecord::Base
belongs_to :role
acts_as_authentic
attr_accessor :old_password
validate :validate_old_password, :if => :required_old_password?
def validate_old_password
errors.add(:old_password) unless valid_password?(self.old_password)
end
def required_old_password!
@old_password_required = true
@password_changed = true
end
def required_old_password?
@old_password_required
end
def active_recently?
last_request_at && last_request_at > 1.day.ago
end
def self.find_by_login(login)
find(:first, :conditions => ["LOWER(login) = ?", login.to_s.downcase])
end
def self.most_active(role)
select = "users.*"
find(:all, :conditions => ["role_id = ?", role], :limit => 13, :select => select, :order => 'login_count DESC')
end
netzke_attribute :password
netzke_attribute :password_confirmation
end
== 修改Role model
app/models/role.rb
class Role < ActiveRecord::Base
has_many :users
end
== 修改 ApplicationController
app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery
layout 'application'
helper_method :current_user_session, :current_user
private
def current_user_session
logger.debug "ApplicationController::current_user_session"
return @current_user_session if defined?(@current_user_session)
@current_user_session = UserSession.find
end
def current_user
logger.debug "ApplicationController::current_user"
return @current_user if defined?(@current_user)
@current_user = current_user_session && current_user_session.user
end
def require_user
logger.debug "ApplicationController::require_user"
unless current_user
store_location
flash[:notice] = "You must be logged in to access this page"
redirect_to new_user_session_url
return false
end
end
def require_no_user
logger.debug "ApplicationController::require_no_user"
if current_user
store_location
flash[:notice] = "You must be logged out to access this page"
redirect_to account_url
return false
end
end
def store_location
session[:return_to] = request.request_uri
end
def redirect_back_or_default(default)
redirect_to(session[:return_to] || default)
session[:return_to] = nil
end
end
== 创建UserSessionsController 控制用户登陆 退出
rails g controller UserSessions new
create app/controllers/user_sessions_controller.rb
route get "user_sessions/new"
invoke erb
create app/views/user_sessions
create app/views/user_sessions/new.html.erb
invoke test_unit
create test/functional/user_sessions_controller_test.rb
invoke helper
create app/helpers/user_sessions_helper.rb
invoke test_unit
create test/unit/helpers/user_sessions_helper_test.rb
=== 修改登陆控制 user_sessions_controller.rb
app/controllers/user_sessions_controller.rb
class UserSessionsController < ApplicationController
before_filter :require_no_user, :only => [:new, :create]
before_filter :require_user, :only => :destroy
def new
@user_session = UserSession.new
end
def create
@user_session = UserSession.new(params[:user_session])
if @user_session.save
flash[:notice] = "Login successful!"
redirect_back_or_default root_url
else
render :action => :new
end
end
def destroy
current_user_session.destroy
flash[:notice] = "Logout successful!"
redirect_back_or_default new_user_session_url
end
end
=== 修改登陆视图 new.html.erb
app/views/user_sessions/new.html.erb
<h2>Welcome Login</h2>
<% form_for @user_session, :url => user_session_path do |f| %>
<%= f.label :login %><br />
<%= f.text_field :login %><br />
<%= f.label :password %><br />
<%= f.password_field :password %><br />
<%= f.check_box :remember_me %><%= f.label :remember_me,"Remember Me " %><%= link_to "Register", new_user_url %>
<div class='align-right bottom borderd'>
<div class='left'><%= flash[:notice] %></div>
<div class='right'><input src="/images/backend/btn-login.png" type="image" /></div>
<div class='clear'></div>
</div>
<br />
<%= f.error_messages %>
<% end %>
== 创建UsersController 注冊用户
rails g controller Users new
create app/controllers/users_controller.rb
route get "users/new"
invoke erb
create app/views/users
create app/views/users/new.html.erb
invoke test_unit
create test/functional/users_controller_test.rb
invoke helper
create app/helpers/users_helper.rb
invoke test_unit
create test/unit/helpers/users_helper_test.rb
=== 修改用户注冊控制
app/controllers/users_controller.rb
class UsersController < ApplicationController
def new
@user = User.new
# render :layout => 'user_sessions'
end
def create
@user = User.new(params[:user].merge(:role => Role.find_by_name('administrator')))
if @user.save
flash[:notice] = "Registration successful."
redirect_back_or_default root_url
else
render :action => :new
end
end
end
=== 修改用户注冊视图
app/views/users/new.html.erb
<h3>New User</h3>
<% form_for @user, :url => user_path do |f| %>
<%= f.error_messages %>
<%= render :partial => "form", :object => f %>
<%= f.submit "Submit" %>
<% end %>
=== 增加用户注冊视图
app/views/users/_form.html.erb
<%= form.label :login %><br />
<%= form.text_field :login %><br />
<br />
<%= form.label :email %><br />
<%= form.text_field :email %><br />
<br />
<%= form.label :password, form.object.new_record? ? nil : "Change password" %><br />
<%= form.password_field :password %><br />
<br />
<%= form.label :password_confirmation %><br />
<%= form.password_field :password_confirmation %><br />
<br />
== 修改布局视图
=== public增加图片和css文件
* 相關文件見附件.
public/images/backend
public/stylesheets/standard.css
public/stylesheets/login.css
=== 登陆布局视图
app/views/layouts/user_sessions.html.haml
!!!
%html
%head
%title="Login"
=stylesheet_link_tag "standard", "login"
%body
#wrapper
#login-box
#content
=yield
#copyright
Copyright © 2011 President office of the 3rd division All rights reserved
=== 用户注冊布局视图
app/views/layouts/users.html.erb
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Register<title>
</head>
<body>
<%= yield %>
</body>
== 修改routes.rb
NetzkeDemo::Application.routes.draw do
# AuthLogic
resource :user_session
resource :user
match 'login' => "user_sessions#new", :as => :login
match 'logout' => "user_sessions#destroy", :as => :logout
end
== 控制登陆访问
app/controllers/demo_controller.rb
class DemoController < ApplicationController
layout "application"
before_filter :require_user
def index
render :inline => "<% title 'Demo App', false %><%= netzke :some_simple_app %>", :layout => true
end
end
== 登陆應用
SimpleApp改為AuthApp, menu繼承SimpleApp
app/components/some_simple_app.rb
class SomeSimpleApp < Netzke::Basepack::AuthApp
# Extend SimpleApp#menu
def menu
["->", :about.action] + super
end
== authlogic警告
DEPRECATION WARNING: save(false) is deprecated, please give save(:validate => false) instead.
修改的文件如下:
* lib/authlogic/session/callbacks.rb: 将save_without_session_maintenance(false)改为save_without_session_maintenance(:validate => false)
* lib/authlogic/acts_as_authentic/password.rb: 将save(false)改为save(:validate => false)
* lib/authlogic/acts_as_authentic/logged_in_status.rb: 将named_scope改为scope