2013-08-24 32 views
2

冗长的问题,但我认为我会尽量彻底。 :)设计登录问题:Rails 3.2.14

我已经按照本教程“如何:允许用户使用自己的用户名或邮箱地址登录”:

https://github.com/plataformatec/devise/wiki/How-To%3a-Allow-users-to-sign-in-using-their-username-or-email-address

所以我显然不是在这方面的专家!我在这里也看到了一些类似的帖子,但没有为我工作。

本质上,我想设置我的应用程序,以便用户使用用户名和密码注册,而不是电子邮件地址。不关心获取用户的电子邮件地址或任何类型的密码恢复。只需要简单的UN和密码认证。我的注册工作很好。我可以整天创建新用户。但是,注销用户后,我无法重新登录。我收到“无效的用户名或密码”消息。

这里就是我的工作:

在控制台中我得到以下401身份验证错误:

Started POST "https://stackoverflow.com/users/sign_in" for 127.0.0.1 at 2013-08-24 17:52:15 -0500 
Processing by Devise::SessionsController#create as HTML 
    Parameters: {"utf8"=>"✓", "authenticity_token"=>"HIFrqmz+LFMTzeULLDedlonWmtUGU0bniseLwcxtv64=", "user"=>{"username"=>"bobbiebear", "password"=>"[FILTERED]", "remember_me"=>"0"}, "commit"=>"Sign in"} 
Completed 401 Unauthorized in 1ms 

我的用户模型user.rb是:

class User < ActiveRecord::Base 
    rolify 
    # Include default devise modules. Others available are: 
    # :token_authenticatable, :confirmable, 
    # :lockable, :timeoutable and :omniauthable 
    devise :database_authenticatable, :registerable, 
     :recoverable, :rememberable, :trackable 

    # Setup accessible (or protected) attributes for your model 
    attr_accessible :role_ids, :as => :admin 
    attr_accessible :username, :password, :password_confirmation, :remember_me 
    attr_accessible :login 
    #attr_accessible :email 

    # Virtual attribute for authenticating by either username or email 
    # This is in addition to a real persisted field like 'username' 
    attr_accessor :login 

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


### This is the correct method you override with the code above 
### def self.find_for_database_authentication(warden_conditions) 
### end 

    def email_required? 
    false 
    end 

    def email_changed? 
    false 
    end 

end 

而且(HAML):

%h2 Sign in 
= simple_form_for(resource, :as => resource_name, :url => session_path(resource_name), :html => {:class => 'form-vertical' }) do |f| 
    = f.input :username, :autofocus => true 
    = f.input :password 
    = f.input :remember_me, :as => :boolean if devise_mapping.rememberable? 
    = f.button :submit, "Sign in", :class => 'btn-primary' 
= render "devise/shared/links" 

而且还

#devise.rb 
Devise.setup do |config| 
    config.authentication_keys = [ :login ] 
    config.confirmation_keys = [ :login ] 
    config.unlock_keys = [ :login ] 
    config.stretches = Rails.env.test? ? 1 : 10 
    config.password_length = 8..128 
    config.sign_out_via = Rails.env.test? ? :get : :delete 
end 

和公正的情况下,这提供任何见解,我的架构:

ActiveRecord::Schema.define(:version => 20130824210400) do 

    create_table "roles", :force => true do |t| 
    t.string "name" 
    t.integer "resource_id" 
    t.string "resource_type" 
    t.datetime "created_at", :null => false 
    t.datetime "updated_at", :null => false 
    end 

    add_index "roles", ["name", "resource_type", "resource_id"], :name => "index_roles_on_name_and_resource_type_and_resource_id" 
    add_index "roles", ["name"], :name => "index_roles_on_name" 

    create_table "users", :force => true do |t| 
    t.string "email",     :default => "" 
    t.string "encrypted_password",  :default => "", :null => false 
    t.string "reset_password_token" 
    t.datetime "reset_password_sent_at" 
    t.datetime "remember_created_at" 
    t.integer "sign_in_count",   :default => 0 
    t.datetime "current_sign_in_at" 
    t.datetime "last_sign_in_at" 
    t.string "current_sign_in_ip" 
    t.string "last_sign_in_ip" 
    t.datetime "created_at",        :null => false 
    t.datetime "updated_at",        :null => false 
    t.string "name" 
    t.string "username" 
    end 

    add_index "users", ["email"], :name => "index_users_on_email" 
    add_index "users", ["reset_password_token"], :name => "index_users_on_reset_password_token", :unique => true 
    add_index "users", ["username"], :name => "index_users_on_username", :unique => true 

    create_table "users_roles", :id => false, :force => true do |t| 
    t.integer "user_id" 
    t.integer "role_id" 
    end 

    add_index "users_roles", ["user_id", "role_id"], :name => "index_users_roles_on_user_id_and_role_id" 

end 

我缺少什么?

编辑和解决方案

所以我恢复到之前,我通过上面提到的教程去了。

下面是我如何解决问题。首先,我决定在用户​​模型(:validatable,:authentication_keys => [:username])中包含devise.rb中注释的authentication_key变量。

我将其从:email改为:username。我也做了:用户名attr_accessible。然后我终于加入

def email_required? 
    false 
    end 

    def email_changed? 
    false 
    end 

所以对于用户模型现在我有:

class User < ActiveRecord::Base 
    rolify 
    # Include default devise modules. Others available are: 
    # :token_authenticatable, :confirmable, 
    # :lockable, :timeoutable and :omniauthable 

    devise :database_authenticatable, :registerable, 
     :recoverable, :rememberable, :trackable, 
     :validatable, :authentication_keys => [:username] 

    # Setup accessible (or protected) attributes for your model 
    attr_accessible :role_ids, :as => :admin 
    attr_accessible :name, :username, :email, :password, :password_confirmation, :remember_me 

    def email_required? 
    false 
    end 

    def email_changed? 
    false 
    end 

end 

然后我更新了意见,使:是不需要的电子邮件中还说:用户名域...

SIGNUP

%h2 Sign up 
= simple_form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => {:class => 'form-vertical' }) do |f| 
    = f.error_notification 
    = display_base_errors resource 
    = f.input :name, :autofocus => true 
    -#= f.input :email, :required => true 
    = f.input :username, :required => true 
    = f.input :password, :required => true 
    = f.input :password_confirmation, :required => true 
    = f.button :submit, 'Sign up', :class => 'btn-primary' 
= render "devise/shared/links" 

并登录

%h2 Sign in 
= simple_form_for(resource, :as => resource_name, :url => session_path(resource_name), :html => {:class => 'form-vertical' }) do |f| 
    -#= f.input :email, :autofocus => true 
    = f.input :username, :autofocus => true 
    = f.input :password 
    = f.input :remember_me, :as => :boolean if devise_mapping.rememberable? 
    = f.button :submit, "Sign in", :class => 'btn-primary' 
= render "devise/shared/links" 

回答

0

不知道,如果你得到了它的工作了,但在这里。

#app/views/devise/registrations/new.html.erb 

<%= f.label :username %> 
<%= f.text_field :username %> 


#config/initializers/devise.rb 

config.authentication_keys = [ :email ] 

to 

config.authentication_keys = [ :username ] 

然后更改窗体来处理用户名而不是电子邮件。

这对我有效,所以我希望它有帮助! (使用Rails 4和Devise 3)

+1

我没有谢谢你!我也加了'def email_required? false end def email_changed? false end'到我的用户类。 – mrilikecoding

0

我不认为虚拟属性login真的需要在这里,你可以只用:username已经实现了这个。

无论如何,我认为问题在于你的看法。你需要改变你的输入字段是:login而不是:username喜欢如下:

%h2 Sign in 
= simple_form_for(resource, :as => resource_name, :url => session_path(resource_name), :html => {:class => 'form-vertical' }) do |f| 
    = f.input :login, :autofocus => true 
    = f.input :password 
    = f.input :remember_me, :as => :boolean if devise_mapping.rememberable? 
    = f.button :submit, "Sign in", :class => 'btn-primary' 
= render "devise/shared/links" 
+0

感谢您的回复。按照您的建议切换视图时,我仍然看到相同的结果。尽管你激励了我。我回到之前,我做了教程,我认为我已经解决了这个问题... – mrilikecoding