关于ruby on rails 3:可靠的身份验证,每次设计无效的密码

Restful_Authentication to Devise invalid password everytime

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
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

和我的一个控制器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
    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

您在那使用的devise是什么版本?我正处于将我的身份验证系统从静态迁移到设计的过程中。 user_signed_in?也不适合我。

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

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