Rails 4 + Devise 3.0 - Authenticate using username and email

徘徊边缘 提交于 2020-01-16 01:00:35

问题


I'm trying to allow users to sign in with either their username or their email address.

as per here: https://github.com/plataformatec/devise/wiki/How-To:-Allow-users-to-sign-in-using-their-username-or-email-address

When ever I try to sign in with either the email or the login this is logged:

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)

its weird the sql isn't checking for the username, so maybe the call on the user is wrong, but its exactly from the devise documentation.

I have read the following:

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

I also reviewed the warden code and the devise code to try and discover if I'm overriding the wrong method in the user.

Any ideas why it is not authenticating with username, when it does with email?

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:


You need to add

config.authentication_keys = [ :login ]

within devise.rb

Also if you want to use login as reset password or confirmation keys you should also add within the same file:

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

You also need to whitelist the login parameter within your application_controller. In the new.html view you have a login form, so you must accept the login parameter for the sign_in instead of the username and email parameters.

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


来源:https://stackoverflow.com/questions/20136052/rails-4-devise-3-0-authenticate-using-username-and-email

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!