Rails 4 + Devise 3.0 - 使用用户名和电子邮件进行身份验证

时间:2013-11-22 02:45:28

标签: email devise ruby-on-rails-4 username

我正在尝试允许用户使用其用户名或电子邮件地址登录。

按此处:https://github.com/plataformatec/devise/wiki/How-To:-Allow-users-to-sign-in-using-their-username-or-email-address

当我尝试使用电子邮件或登录信息登录时,会记录下来:

Started POST "/users/sign_in" for 192.168.2.8 at 2013-11-22 10:11:50 +0800
Processing by Devise::SessionsController#create as HTML
  Parameters: {"utf8"=>"â", "authenticity_token"=>"WVTOKWQ8yJAJSu3NmXi3skJ8UC8zXY7qGZj7qbM3cr0=", "user"=>{"email"=>"testuser", "password"=>"password"}, "commit"=>"Sign in"}
  User Load (3.3ms)  SELECT "users".* FROM "users" WHERE "users"."email" = 'testuser' ORDER BY "users"."id" ASC LIMIT 1
Completed 401 Unauthorized in 20ms
Processing by Devise::SessionsController#new as HTML
  Parameters: {"utf8"=>"â", "authenticity_token"=>"WVTOKWQ8yJAJSu3NmXi3skJ8UC8zXY7qGZj7qbM3cr0=", "user"=>{"email"=>"rtype", "password"=>"password"}, "commit"=>"Sign in"}
  Rendered devise/sessions/new.html.erb within layouts/application (6.4ms)
Completed 200 OK in 80ms (Views: 62.6ms | ActiveRecord: 0.0ms)

奇怪的是sql没有检查用户名,所以也许对用户的调用是错误的,但它完全来自设计文档。

我已阅读以下内容:

Adding Username to devise rails 4 Logging in with username using Devise with Rails 4

我还查看了监护人代码和设计代码,试图发现我是否覆盖了用户的错误方法。

任何想法,为什么它不使用用户名进行身份验证,当它与电子邮件一起使用时?

ApplicationController.rb

class ApplicationController < ActionController::Base
  protect_from_forgery

  before_filter :configure_permitted_parameters, if: :devise_controller?

  protected
    def configure_permitted_parameters
      devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:username, :email, :password, :password_confirmation) }
      devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:username, :email, :password, :remember_me) }

      # Need to add other user fields like gender etc.
      devise_parameter_sanitizer.for(:account_update) {|u| u.permit(:email, :password, :password_confirmation, :current_password)}
    end
end

User.rb

class User < ActiveRecord::Base

  devise :database_authenticatable, :registerable, :confirmable, :encryptable, :recoverable, :rememberable, :trackable, :validatable

  attr_accessor :login # This is used to add the login for allowing user to sign in with both email or username

  # Validations
  validates :username, presence: true, length: {maximum: 255}, uniqueness: { case_sensitive: false }, format: { with: /\A[a-zA-Z0-9]*\z/, message: "may only contain letters and numbers." }

  # Overwrite devise’s find_for_database_authentication method in user model
  def self.find_first_by_auth_conditions(warden_conditions)
    conditions = warden_conditions.dup
    if login = conditions.delete(:username)
      where(conditions).where(["lower(username) = :value OR lower(email) = :value", { :value => login.downcase }]).first
    else
      where(conditions).first
    end
  end
end

new.html

<fieldset>
<%= form_for(resource, :as => resource_name, :url => session_path(resource_name),  :html => { :class => 'form-horizontal' }) do |f| %>
  <div class="control-group">
    <%= f.label :login, "Email or Username" %>
    <div class="controls"><%= f.text_field :login, :autofocus => true %></div>
  </div>

  <div class="control-group">
    <%= f.label :password %>
    <div class="controls"><%= f.password_field :password %></div>
  </div>

  <div class="form-actions">
    <%= f.submit "Sign in", :class => "btn btn-primary", data: { disable_with: 'Working...' } %>  <%= link_to "Forgot password?", new_password_path(resource_name), :class => "btn" %>
  </div>
<% end %>
</fieldset>

Devise.rb

config.secret_key = 'Omitted for security'
config.mailer_sender = 'Omitted for security'
config.case_insensitive_keys = [ :email ]
config.strip_whitespace_keys = [ :email ]
config.skip_session_storage = [:http_auth]
config.stretches = Rails.env.test? ? 1 : 10
config.reconfirmable = true
config.password_length = 8..128
config.reset_password_within = 6.hours
config.encryptor = :sha512
config.sign_out_via = :delete

1 个答案:

答案 0 :(得分:3)

您需要添加

config.authentication_keys = [ :login ]
在devise.rb中

此外,如果您想使用登录作为重置密码或确认密钥,您还应该在同一文件中添加:

config.reset_password_keys = [ :login ]
config.confirmation_keys = [ :login ]

您还需要将application_controller中的login参数列入白名单。在new.html视图中,您有一个登录表单,因此您必须接受sign_in的登录参数,而不是用户名和电子邮件参数。

devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:login, :password, :remember_me) }
相关问题