Gem devise 可以使用用户名和邮箱登陆出错 ,各位看看是什么原因

geekontheway · 2012年02月08日 · 最后由 songlipeng2003 回复于 2012年04月28日 · 5892 次阅读

错误信息

Started POST "/admins/sign_in" for 127.0.0.1 at 2012-02-08 10:56:11 +0800
Processing by Devise::SessionsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"2EGtbBAvYheW53Bxx6VEK3vqyE6FjlF7obbhKGhLNJE=", "login"=>"[email protected]", "admin"=>{"password"=>"[FILTERED]"}}
Completed 401 Unauthorized in 6ms

admin.rb

attr_accessible :email, :username, :password, :password_confirmation, :remember_me
attr_accessor :login

def self.find_for_database_authentication(warden_conditions)
    conditions = warden_conditions.dup
    login = conditions.delete(:login)
    where(conditions).where(["lower(username) = :value OR lower(email) = :value", {:value => login.strip.downcase}]).first
  end

  protected

  # Attempt to find a user by it's email. If a record is found, send new
  # password instructions to it. If not user is found, returns a new user
  # with an email not found error.
  def self.send_reset_password_instructions(attributes={})
    recoverable = find_recoverable_or_initialize_with_errors(reset_password_keys, attributes, :not_found)
    recoverable.send_reset_password_instructions if recoverable.persisted?
    recoverable
  end

  def self.find_recoverable_or_initialize_with_errors(required_attributes, attributes, error=:invalid)
    (case_insensitive_keys || []).each { |k| attributes[k].try(:downcase!) }

    attributes = attributes.slice(*required_attributes)
    attributes.delete_if { |key, value| value.blank? }

    if attributes.size == required_attributes.size
      if attributes.has_key?(:login)
        login = attributes.delete(:login)
        record = find_record(login)
      else
        record = where(attributes).first
      end
    end

    unless record
      record = new

      required_attributes.each do |key|
        value = attributes[key]
        record.send("#{key}=", value)
        record.errors.add(key, value.present? ? error : :blank)
      end
    end
    record
  end

  def self.find_record(login)
    where(["username = :value OR email = :value", {:value => login}]).first
  end

end

View

<input id="admin_login" name="login" size="30" type="text" class="validate[required]"/>
<input id="admin_password" name="admin[password]" size="30" type="password" class="validate[required]"/>

devise.rb

config.authentication_keys = [ :login ]

也会报这个错误 WARNING: Can't verify CSRF token authenticity

你不断刷新,看看源代码里面的 <meta content="..." name="csrf-token" /> 会不会每次都不同。

#4 楼 @huacnlee 我现在按照 stackoverflow 上的另外一种方法尝试了,只需在 admin.rb 中

def self.find_for_database_authentication(conditions={})
  self.where("username = ?", conditions[:email]).limit(1).first ||
  self.where("email = ?", conditions[:email]).limit(1).first
end

其他地方都不用改,这个时候通过 email 可以登陆,username 则不行

Started POST "/admins/sign_in" for 127.0.0.1 at 2012-02-08 13:33:26 +0800
Processing by Devise::SessionsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"KfbBHvHlAIa+EdRh6A83ei5IORfAnr0Jv6vsYH5oOXk=", "admin"=>{"email"=>"xiao", "password"=>"[FILTERED]"}}
  Admin Load (0.3ms)  SELECT `admins`.* FROM `admins` WHERE `admins`.`email` = 'xiao' LIMIT 1
Completed 401 Unauthorized in 1ms

self.find_for_database_authentication 这个方法没生效吗?为什么没有查询 WHERE admins.username = 'xiao' LIMIT 1

是按钮官方 wiki 的方法做的吗?我照着这个方法做的,没有问题。 https://github.com/plataformatec/devise/wiki/How-To:-Allow-users-to-sign-in-using-their-username-or-email-address

#7 楼 @bindiry 谢谢哈 已经解决了

Started POST "/admins/sign_in" for 127.0.0.1 at 2012-02-08 13:33:26 +0800
Processing by Devise::SessionsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"KfbBHvHlAIa+EdRh6A83ei5IORfAnr0Jv6vsYH5oOXk=", "admin"=>{"email"=>"xiao", "password"=>"[FILTERED]"}}
  Admin Load (0.3ms)  SELECT `admins`.* FROM `admins` WHERE `admins`.`email` = 'xiao' LIMIT 1
Completed 401 Unauthorized in 1ms


#8 楼 @geekontheway

这个问题怎么解决的啊?我也是这样啊

需要 登录 后方可回复, 如果你还没有账号请 注册新账号