`

Rails之用户登录

 
阅读更多

用rails实现一个简单的用户网站登录模块

>rails -v

Rails 3.2.13

首先创建一个用户信息的model,设置表结构如下(包含昵称,加密密码以及salt值)(*_create_users.rb)

class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :name
      t.string :hashed_password
      t.string :salt

      t.timestamps
    end
  end
end

接着修改model文件如下(model/user.rb):

class User < ActiveRecord::Base

  #配置可访问属性
  attr_accessible :hashed_password, :name, :salt, :password, :password_confirmation
  attr_accessor :password
  
  #数据验证
  validates_presence_of :name
  validates_uniqueness_of :name
  attr_accessor :password_confirmation
  validates_confirmation_of :password
  
  #供controller调用的鉴权函数
  def self.authenticate(name, password)
    user = self.find_by_name(name)
    if user
       expected_password = encrypted_password(password, user.salt)
       if user.hashed_password != expected_password
         user = nil
       end
    end
    user
  end
  
  # 'password' is a virtual attribute
  def password
    @password
  end
  def password=(pwd)
    @password = pwd
    return if pwd.blank?
    create_new_salt
    self.hashed_password = User.encrypted_password(self.password, self.salt)
  end
  
private
  
  #计算密码加密结果
  def create_new_salt
    self.salt = self.object_id.to_s + rand.to_s
  end
  def self.encrypted_password(password, salt)
    string_to_hash = password + "wibble" + salt
    Digest::SHA1.hexdigest(string_to_hash)
  end
end

 创建controller(admin),增加login/logout/register/index等action如下,其中index表示受限资源

class AdminController < ApplicationController

  def register
    if request.post?
		@user = User.new(params[:user])
		if @user.save
		  session[:user_id] = @user.id
		  uri = session[:original_uri]	#跳转到登录之前的页面
	      flash[:notice] = "User #{@user.name} was successfully created."
		  redirect_to(uri || { :action => "index" })
		else
		  redirect_to({ :action => "register" })
		end
	else
	  @user = User.new
	end
  end

  def login
	if request.post?
	  user = User.authenticate(params[:name], params[:password])
	  if user
	    session[:user_id] = user.id
	    uri = session[:original_uri]	#跳转到登录之前的页面
        session[:original_uri] = nil
        redirect_to(uri || { :action => "index" })
	  else
	    flash.now[:notice] = "Invalid user/password combination"
		redirect_to({ :action => "index" })
	  end
    end
  end

  def logout
    session[:user_id] = nil
    flash[:notice] = "Logged out"
    redirect_to(:action => "login" )
  end

  def index
    @user_id = session[:user_id]
  end
end

受限资源内容如下:

<h1>Restricted Resources</h1>
User ID <%= @user_id %>.
<%= link_to 'Logout', :controller => 'admin', :action => 'logout' %>

register的view如下(view/admin/register.html.erb)

<div class="depot-form">
<%= form_for @user, :url => url_for(:controller => 'admin', :action => "register") do |f| %>
  <div class="field">
    <%= f.label :name %>:
    <%= f.text_field :name %>
  </div>
  <div class="field">
    <%= f.label :user_password, 'Password' %>:
    <%= f.password_field :password, :size => 40 %>
  </div>
  <div class="field">
    <%= f.label :user_password_confirmation, 'Confirm' %>:
    <%= f.password_field :password_confirmation, :size => 40 %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>
</div>

login的view如下(view/admin/login.html.erb)

<div class="depot-form">
<%= form_tag do %>
<fieldset>
<legend>Please Log In</legend>
<div>
<label for="name">Name:</label>
<%= text_field_tag :name, params[:name] %>
</div>
<div>
<label for="password">Password:</label>
<%= password_field_tag :password, params[:password] %>
</div>
<div>
<%= submit_tag "Login" %>
</div>
</fieldset>
<% end %>

<%= link_to 'Register', :controller => 'admin', :action => 'register' %>
</div>

然后需要配置application_controller.rb,因为所有controller都继承它,在这里可以轻松实现统一的资源限制,我们就不必在每一个controller中单独限制资源了

class ApplicationController < ActionController::Base
  #配置指定action以外都需要进行用户权限验证
  before_filter :authorize, :except => [:login, :register]

  protect_from_forgery
  
protected

  #用户权限验证函数,失败则跳转回登录页面
  def authorize
    unless User.find_by_id(session[:user_id])
	  session[:original_uri] = request.url
      flash[:notice] = "Please log in"
      redirect_to :controller => 'admin' , :action => 'login'
    end
  end
end
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics