Restful Authentication每次设计无效密码

时间:2011-06-27 16:48:54

标签: ruby-on-rails-3 authentication devise restful-authentication

我刚刚在当前应用中将Restful_Authentication迁移到了Devise。我已经将crypted_pa​​ssword的变量更改为encrypted_pa​​ssword,并将salt更改为我的模型文件中的password_salt,因此当我将它们放入put显示时,这两个密码匹配。我已按照https://github.com/plataformatec/devise/wiki/How-To:-Migrate-from-restful_authentication-to-Devise-上的教程,但是,user_signed_in?在模型中返回false,current_user返回true但无法获取ID ...下面是我的模型:

require 'digest/sha1'

class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
   :recoverable, :rememberable, :confirmable, :validatable, 
   :encryptable, :encryptor => :restful_authentication_sha1

#attr_accessor :password
#set_table_name 'users'

#validates :login, :presence   => true,
 #                 :uniqueness => true,
 #                 :length     => { :within => 3..40 },
 #                 :format     => { :with => Authentication.login_regex, :message => Authentication.bad_login_message }

#validates :name,  :format     => { :with => Authentication.name_regex, :message =>     Authentication.bad_name_message },
#                  :length     => { :maximum => 100 },
 #                 :allow_nil  => true

#validates :email, :presence   => true,
  #                 :uniqueness => true,
#                  :format     => { :with => Authentication.email_regex, :message =>    Authentication.bad_email_message },
  #                 :length     => { :within => 6..100 }

validates_presence_of     :login, :email, :first_name, :last_name, :user_type
validates_presence_of     :password,                   :if => :password_required?
validates_presence_of     :password_confirmation,      :if => :password_required?
validates_length_of       :password, :within => 4..40, :if => :password_required?
validates_confirmation_of :password,                   :if => :password_required?
validates_length_of       :login,    :within => 3..40
validates_length_of       :email,    :within => 3..100
validates_uniqueness_of   :login, :case_sensitive => false
before_save :encrypt_password
before_create :make_activation_code 

# HACK HACK HACK -- how to do attr_accessible from here?
# prevents a user from submitting a crafted form that bypasses activation
# anything else you want your user to change should be added here.
has_many :assets
attr_accessible :login, :email, :name, :password, :password_confirmation

 class UserType
  ADMIN = 'Admin'
  UPDATER = 'Updater'
  VIEWER = 'Viewer'
end

 def self.GetUserTypes
 usertypes = [UserType::ADMIN, UserType::UPDATER, UserType::VIEWER]
return usertypes
end

has_many :assets
# Authenticates a user by their login name and unencrypted password.  Returns the user   or nil.
#
# uff.  this is really an authorization, not authentication routine.  
# We really need a Dispatch Chain here or something.
# This will also let us return a human error message.
#
def activate
  @activated = true
  self.activated_at = Time.now.utc
  self.activation_code = nil
  save(false)
end
def active?
  # the existence of an activation code means they have not activated yet
  activation_code.nil?
  end

def self.authenticate(login, password)
  puts ("===IN AUTHENTICATE===")
  return nil if login.blank? || password.blank?
  u = find_by_login(login.downcase) # need to get the salt
  u && u.authenticated?(password) ? u : nil
end

#def destroy
#  puts ("**********In User Model destroy")
#end

def login=(value)
  write_attribute :login, (value ? value.downcase : nil)
end

def email=(value)
  write_attribute :email, (value ? value.downcase : nil)
  end

  def authenticated?(password)
  puts ("IN AUTHENTICATED?")
  encrypted_password == encrypt(password)
end
  def encrypt(password)
  self.class.encrypt(password, password_salt)
end
 def self.encrypt(password, password_salt)
  Digest::SHA1.hexdigest("--#{password_salt}--#{password}--")
end

def get_name_last_first
return last_name + ", " + first_name
end

 def remember_token?
   remember_token_expires_at && Time.now.utc < remember_token_expires_at 
end
 # These create and unset the fields required for remembering users between browser  closes
def remember_me
  remember_me_for 2.weeks
 end

def remember_me_for(time)
  remember_me_until time.from_now.utc
end

def remember_me_until(time)
  self.remember_token_expires_at = time
  self.remember_token            = encrypt("#{email}--#{remember_token_expires_at}")
    save(false)
end

def forget_me
  self.remember_token_expires_at = nil
  self.remember_token            = nil
  save(false)
end

# Returns true if the user has just been activated.
def recently_activated?
  @activated
end

protected
  # before filter 
  def encrypt_password
  return if password.blank?
  self.password_salt = Digest::SHA1.hexdigest("--#{Time.now.to_s}--#{login}--") if new_record?
  self.encrypted_password = encrypt(password)
end

def password_required?
  encrypted_password.blank? || !password.blank?
end

def make_activation_code

  self.activation_code = Digest::SHA1.hexdigest( Time.now.to_s.split(//).sort_by {rand}.join )
end

end

和我的一个控制器:

    class AssetsController < ApplicationController

  before_filter :validate_user_type, :except => [:myassets, :show]

  # GET /assets
  # GET /assets.xml
  def index

    # check incoming page param, if not present, set it to 1
    searchPage = 1
    if params[:page] != nil
      searchPage = params[:page]
    end
    #@assets = Asset.find(:all, :order => "asset_id ASC")
    @assets = Asset.paginate(:per_page => 25, :page => searchPage, :order => "asset_id ASC")

    # setup the action menu options
    @actionMenuOptions = []

    option1 = ActionMenuOption.new("My Assets", assets_path + "/myassets", User::UserType::UPDATER )
    option2 = ActionMenuOption.new("New Asset", new_asset_path, User::UserType::UPDATER)
    option3 = ActionMenuOption.new("Export to Excel", assets_path + "/exporttoexcel.csv", User::UserType::UPDATER)
    @actionMenuOptions[0] = option1 
    @actionMenuOptions[1] = option2
    @actionMenuOptions[2] = option3

    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :xml => @assets }
      format.csv  { render :csv => @assets }
    end
  end

  # GET /assets/exporttoexcel.csv
  def exporttoexcel
    @assets = Asset.find(:all, :order => "asset_id ASC")

    # we should never call this action without the .csv added
    respond_to do |format|
      #format.html # index.html.erb
      #format.xml  { render :xml => @assets }
      format.csv  { render :csv => @assets }
    end
  end


  # GET assets/myassets
  # GET assets/myassets.xml
  def myassets
    # check incoming page param, if not present, set it to 1
    searchPage = 1
    if params[:page] != nil
      searchPage = params[:page]
    end

    #@assets = Asset.find(:all, :conditions => { :user_id => current_user.id }, :order => "asset_id ASC")
    @assets = Asset.paginate(:conditions => { :user_id => current_user.id }, :per_page => 25, :page => searchPage, :order => "asset_id ASC")     

    respond_to do |format|
      format.html # myassets.html.erb
      format.xml  { render :xml => @assets }
      format.csv  { render :csv => @assets }
    end
  end

  # GET /assets/1
  # GET /assets/1.xml
  def show
    @asset = Asset.find(params[:id])

    respond_to do |format|
      format.html # show.html.erb
      format.xml  { render :xml => @asset }
    end
  end

  # GET /assets/new
  # GET /assets/new.xml
  def new
    @asset = Asset.new

    respond_to do |format|
      format.html # new.html.erb
      format.xml  { render :xml => @asset }
    end
  end

  # GET /assets/1/edit
  def edit
    @asset = Asset.find(params[:id])
  end

  # POST /assets
  # POST /assets.xml
  def create

    @asset = Asset.new(params[:asset])
    @asset.last_status_update = Time.now

    respond_to do |format|
      if @asset.save
        flash[:notice] = 'Asset was successfully created.'
        format.html { redirect_to :controller => 'assets', :action => 'index' }
        format.xml  { render :xml => @asset, :status => :created, :location => @asset }
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @asset.errors, :status => :unprocessable_entity }
      end
    end
  end

  # PUT /assets/1
  # PUT /assets/1.xml
  def update

    @asset = Asset.find(params[:id])

    # check to see if the last status update needs to be updated
    if @asset.status_id != params[:asset][:status_id] || 
       @asset.user_id != params[:asset][:user_id] ||
       @asset.location_id != params[:asset][:location_id]
      puts "*** Changing last status update... ****"
      @asset.last_status_update = Time.now
    end

    respond_to do |format|
      if @asset.update_attributes(params[:asset])
        flash[:notice] = 'Asset was successfully updated.'
        format.html { redirect_to :controller => 'assets', :action => 'index' }
        format.xml  { head :ok }
      else
        format.html { render :action => "edit" }
        format.xml  { render :xml => @asset.errors, :status => :unprocessable_entity }
      end
    end
  end

  # DELETE /assets/1
  # DELETE /assets/1.xml
  def destroy
    @asset = Asset.find(params[:id])
    @asset.destroy

    respond_to do |format|
      format.html { redirect_to(assets_url) }
      format.xml  { head :ok }
    end
  end

  # GET assets/search
  # GET assets/search
  def search

    @searchBox = params[:search_field]

    # this is very NON-rails'ish' but I needed to perform the join on assets and users so I could 
    # search user name in the global search, therefore use the find_by_sql call; I had to also use a 
    # union because the assets may have a null user id in the assigned_to field.
    searchSQL = "SELECT a.id, a.asset_id, a.name, a.serial_number, a.category_id, a.status_id, a.user_id, a.location_id" +
                " from assets a where a.asset_ID LIKE '%" + @searchBox +
                "%' OR a.name LIKE '%" + @searchBox + "%'" + 
                "UNION " + 
                "SELECT a.id, a.asset_id, a.name, a.serial_number, a.category_id, a.status_id, a.user_id, a.location_id" +
                " from assets a, users u where a.user_id = u.id AND (u.first_name LIKE '%" + @searchBox + 
                "%' OR u.last_name LIKE '%" + @searchBox + "%')" + 
                "order by asset_id ASC"

    # check incoming page param, if not present, set it to 1
    searchPage = 1
    if params[:page] != nil
      searchPage = params[:page]
    end

    #@assets = Asset.find_by_sql(searchSQL)
    @assets = Asset.paginate_by_sql(searchSQL, :page => searchPage, :per_page => 25)  

    respond_to do |format|
      format.html # search.html.erb
      format.xml  { render :xml => @assets }
      format.csv  { render :csv => @assets }
    end
  end

  private

  def validate_user_type
    if (current_user.user_type == User::UserType::VIEWER )
      redirect_to :controller => 'assets', :action => 'myassets'
    end
  end

end

1 个答案:

答案 0 :(得分:0)

你在那里使用的设计版本是什么?我正在将我的auth系统从restful迁移到devise。 user_signed_in?也不适合我。

但是,signed_in?(:user)正在为我工​​作。我还没有在用户登录后检查这种情况。但至少在用户没有登录时它会返回false。

参考:http://groups.google.com/group/plataformatec-devise/browse_thread/thread/e87dd5d00ce0217c?pli=1