針對 netzke 使用 authlogic 做登录验证

= 使用 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 &copy; 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

你可能感兴趣的:(css,F#,Flash,ActiveRecord,Rails)