我正在尝试将Authlogic设置为我的默认身份验证系统。我希望用户能够使用他们的用户名或电子邮件登录。为了实现这一点,我做了以下操作:
app/model/user.rb:
class User < ActiveRecord::Base
#add authlogic authentications
acts_as_authentic do |c|
c.find_by_login_method :find_by_username_or_email
end
attr_accessible :username, :email, :password, :password_confirmation
validates :username, :presence => true,
:length => { :within => 3..20 },
:uniqueness => true,
:format => { :with => /A[a-z0-9][a-z0-9-]+[a-z0-9]z/ }
validates :email, :presence => true,
:format => { :with => /A[w+-.]+@[a-zd-.]+.[a-z]+z/i },
:uniqueness => { :case_sensative => false },
:length => { :maximum => 255 }
validates :password, :presence => true,
:confirmation => true,
:length => { :within => 6..40 }
def self.find_by_username_or_email(username_or_email)
find_by_username(username_or_email) || find_by_email(username_or_email)
end
end
app/model/session.rb:
class Session < Authlogic::Session::Base
end
app/controller/sessions_controller.rb:
class SessionsController < ApplicationController
before_filter :require_no_user, :only => [:new, :create]
before_filter :require_user, :only => :destroy
def new
@session = Session.new
end
def create
username = User.find_by_email(params[:session][:username_or_email]).username
username ||= params[:session][:username_or_email]
@session = Session.new(params[:session])
if @session.save
flash[:notice] = "Login successful!"
redirect_back_or_default :users
else
render :action => :new
end
end
def destroy
current_session.destroy
redirect_back_or_default new_session_url
end
end
app/views/sessions/new.html.erb:
<h1>Sign In</h1>
<%= render 'login_form' %>
app/views/sessions/_login_form.html.erb:
<%= form_for @session do |f| %>
<div class="field">
<%= f.label 'Username or Email' %><br />
<%= f.text_field :login %>
</div>
<div class="field">
<%= f.label :password %><br />
<%= f.password_field :password %>
</div>
<div class="actions">
<%= f.submit "Sign In", :class => "button" %>
</div>
<% end %>
config/routes.rb:
Test::Application.routes.draw do
resources :users
resources :sessions, :only => :create
match '/signup', :to => 'users#new'
match '/signin', :to => 'sessions#new', :as => :signin
match '/signout', :to => 'sessions#destroy', :as => :signout
end
当我运行rails服务器并尝试连接到http://localhost:3000/signin
时,它会给出以下错误:
undefined method `login_field' for Object:Class
完整堆栈跟踪如下:
authlogic (3.0.3) lib/authlogic/session/password.rb:90:in `login_field'
authlogic (3.0.3) lib/authlogic/session/password.rb:213:in `login_field'
authlogic (3.0.3) lib/authlogic/session/password.rb:118:in `initialize'
authlogic (3.0.3) lib/authlogic/session/activation.rb:48:in `initialize'
authlogic (3.0.3) lib/authlogic/session/klass.rb:64:in `initialize'
authlogic (3.0.3) lib/authlogic/session/scopes.rb:79:in `initialize'
authlogic (3.0.3) lib/authlogic/session/persistence.rb:37:in `new'
authlogic (3.0.3) lib/authlogic/session/persistence.rb:37:in `find'
app/controllers/application_controller.rb:15:in `current_session'
app/controllers/application_controller.rb:20:in `current_user'
app/controllers/application_controller.rb:33:in `require_no_user'
activesupport (3.0.7) lib/active_support/callbacks.rb:447:in `_run__2106190539632311804__process_action__1284228636937718599__callbacks'
activesupport (3.0.7) lib/active_support/callbacks.rb:410:in `_run_process_action_callbacks'
activesupport (3.0.7) lib/active_support/callbacks.rb:94:in `run_callbacks'
actionpack (3.0.7) lib/abstract_controller/callbacks.rb:17:in `process_action'
actionpack (3.0.7) lib/action_controller/metal/instrumentation.rb:30:in `block in process_action'
activesupport (3.0.7) lib/active_support/notifications.rb:52:in `block in instrument'
activesupport (3.0.7) lib/active_support/notifications/instrumenter.rb:21:in `instrument'
activesupport (3.0.7) lib/active_support/notifications.rb:52:in `instrument'
actionpack (3.0.7) lib/action_controller/metal/instrumentation.rb:29:in `process_action'
actionpack (3.0.7) lib/action_controller/metal/rescue.rb:17:in `process_action'
actionpack (3.0.7) lib/abstract_controller/base.rb:119:in `process'
actionpack (3.0.7) lib/abstract_controller/rendering.rb:41:in `process'
actionpack (3.0.7) lib/action_controller/metal.rb:138:in `dispatch'
actionpack (3.0.7) lib/action_controller/metal/rack_delegation.rb:14:in `dispatch'
actionpack (3.0.7) lib/action_controller/metal.rb:178:in `block in action'
actionpack (3.0.7) lib/action_dispatch/routing/route_set.rb:62:in `call'
actionpack (3.0.7) lib/action_dispatch/routing/route_set.rb:62:in `dispatch'
actionpack (3.0.7) lib/action_dispatch/routing/route_set.rb:27:in `call'
rack-mount (0.6.14) lib/rack/mount/route_set.rb:148:in `block in call'
rack-mount (0.6.14) lib/rack/mount/code_generation.rb:93:in `block in recognize'
rack-mount (0.6.14) lib/rack/mount/code_generation.rb:68:in `optimized_each'
rack-mount (0.6.14) lib/rack/mount/code_generation.rb:92:in `recognize'
rack-mount (0.6.14) lib/rack/mount/route_set.rb:139:in `call'
actionpack (3.0.7) lib/action_dispatch/routing/route_set.rb:493:in `call'
sass (3.1.1) lib/sass/plugin/rack.rb:54:in `call'
actionpack (3.0.7) lib/action_dispatch/middleware/best_standards_support.rb:17:in `call'
actionpack (3.0.7) lib/action_dispatch/middleware/head.rb:14:in `call'
rack (1.2.2) lib/rack/methodoverride.rb:24:in `call'
actionpack (3.0.7) lib/action_dispatch/middleware/params_parser.rb:21:in `call'
actionpack (3.0.7) lib/action_dispatch/middleware/flash.rb:182:in `call'
actionpack (3.0.7) lib/action_dispatch/middleware/session/abstract_store.rb:149:in `call'
actionpack (3.0.7) lib/action_dispatch/middleware/cookies.rb:302:in `call'
activerecord (3.0.7) lib/active_record/query_cache.rb:32:in `block in call'
activerecord (3.0.7) lib/active_record/connection_adapters/abstract/query_cache.rb:28:in `cache'
activerecord (3.0.7) lib/active_record/query_cache.rb:12:in `cache'
activerecord (3.0.7) lib/active_record/query_cache.rb:31:in `call'
activerecord (3.0.7) lib/active_record/connection_adapters/abstract/connection_pool.rb:354:in `call'
actionpack (3.0.7) lib/action_dispatch/middleware/callbacks.rb:46:in `block in call'
activesupport (3.0.7) lib/active_support/callbacks.rb:416:in `_run_call_callbacks'
actionpack (3.0.7) lib/action_dispatch/middleware/callbacks.rb:44:in `call'
rack (1.2.2) lib/rack/sendfile.rb:107:in `call'
actionpack (3.0.7) lib/action_dispatch/middleware/remote_ip.rb:48:in `call'
actionpack (3.0.7) lib/action_dispatch/middleware/show_exceptions.rb:47:in `call'
railties (3.0.7) lib/rails/rack/logger.rb:13:in `call'
rack (1.2.2) lib/rack/runtime.rb:17:in `call'
activesupport (3.0.7) lib/active_support/cache/strategy/local_cache.rb:72:in `call'
rack (1.2.2) lib/rack/lock.rb:11:in `block in call'
<internal:prelude>:10:in `synchronize'
rack (1.2.2) lib/rack/lock.rb:11:in `call'
actionpack (3.0.7) lib/action_dispatch/middleware/static.rb:30:in `call'
railties (3.0.7) lib/rails/application.rb:168:in `call'
railties (3.0.7) lib/rails/application.rb:77:in `method_missing'
railties (3.0.7) lib/rails/rack/log_tailer.rb:14:in `call'
rack (1.2.2) lib/rack/content_length.rb:13:in `call'
rack (1.2.2) lib/rack/handler/webrick.rb:52:in `service'
/Users/helixed/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/webrick/httpserver.rb:111:in `service'
/Users/helixed/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/webrick/httpserver.rb:70:in `run'
/Users/helixed/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/webrick/server.rb:183:in `block in start_thread'
我真的不明白为什么会发生这种事。如果我使用find_by_login_method
,那么为什么Authlogic甚至需要login_field
?
更新
我更新了代码以匹配Olivier L的答案。控制器坏了,但我认为它离我们更近了。
app/models/user.rb:
class User < ActiveRecord::Base
#add authlogic authentications
acts_as_authentic do |c|
c.session_class = Session
c.find_by_login_method :find_by_username_or_email
end
attr_accessible :username, :email, :password, :password_confirmation
validates :username, :presence => true,
:length => { :within => 3..20 },
:uniqueness => true,
:format => { :with => /A[a-z0-9][a-z0-9-]+[a-z0-9]z/ }
validates :email, :presence => true,
:format => { :with => /A[w+-.]+@[a-zd-.]+.[a-z]+z/i },
:uniqueness => { :case_sensative => false },
:length => { :maximum => 255 }
validates :password, :presence => true,
:confirmation => true,
:length => { :within => 6..40 }
def self.find_by_username_or_email(username_or_email)
find_by_username(username_or_email) || find_by_email(username_or_email)
end
end
app/models/session.rb:
class Session < Authlogic::Session::Base
authenticate_with User
end
我现在得到错误:
undefined method `find_by_login_method' for #<Class:0x00000101a77ba8>
以下是应用程序跟踪:
activerecord (3.0.7) lib/active_record/base.rb:984:in `method_missing'
app/models/user.rb:30:in `block in <class:User>'
authlogic (3.0.3) lib/authlogic/acts_as_authentic/base.rb:36:in `acts_as_authentic'
app/models/user.rb:28:in `<class:User>'
app/models/user.rb:25:in `<top (required)>'
activesupport (3.0.7) lib/active_support/dependencies.rb:454:in `load'
activesupport (3.0.7) lib/active_support/dependencies.rb:454:in `block in load_file'
activesupport (3.0.7) lib/active_support/dependencies.rb:596:in `new_constants_in'
activesupport (3.0.7) lib/active_support/dependencies.rb:453:in `load_file'
activesupport (3.0.7) lib/active_support/dependencies.rb:340:in `require_or_load'
activesupport (3.0.7) lib/active_support/dependencies.rb:491:in `load_missing_constant'
activesupport (3.0.7) lib/active_support/dependencies.rb:183:in `block in const_missing'
activesupport (3.0.7) lib/active_support/dependencies.rb:181:in `each'
activesupport (3.0.7) lib/active_support/dependencies.rb:181:in `const_missing'
activesupport (3.0.7) lib/active_support/dependencies.rb:503:in `load_missing_constant'
activesupport (3.0.7) lib/active_support/dependencies.rb:183:in `block in const_missing'
activesupport (3.0.7) lib/active_support/dependencies.rb:181:in `each'
activesupport (3.0.7) lib/active_support/dependencies.rb:181:in `const_missing'
app/models/session.rb:2:in `<class:Session>'
app/models/session.rb:1:in `<top (required)>'
activesupport (3.0.7) lib/active_support/dependencies.rb:454:in `load'
activesupport (3.0.7) lib/active_support/dependencies.rb:454:in `block in load_file'
activesupport (3.0.7) lib/active_support/dependencies.rb:596:in `new_constants_in'
activesupport (3.0.7) lib/active_support/dependencies.rb:453:in `load_file'
activesupport (3.0.7) lib/active_support/dependencies.rb:340:in `require_or_load'
activesupport (3.0.7) lib/active_support/dependencies.rb:491:in `load_missing_constant'
activesupport (3.0.7) lib/active_support/dependencies.rb:183:in `block in const_missing'
activesupport (3.0.7) lib/active_support/dependencies.rb:181:in `each'
activesupport (3.0.7) lib/active_support/dependencies.rb:181:in `const_missing'
activesupport (3.0.7) lib/active_support/dependencies.rb:503:in `load_missing_constant'
activesupport (3.0.7) lib/active_support/dependencies.rb:183:in `block in const_missing'
activesupport (3.0.7) lib/active_support/dependencies.rb:181:in `each'
activesupport (3.0.7) lib/active_support/dependencies.rb:181:in `const_missing'
app/controllers/application_controller.rb:15:in `current_session'
app/controllers/application_controller.rb:20:in `current_user'
app/controllers/application_controller.rb:33:in `require_no_user'
activesupport (3.0.7) lib/active_support/callbacks.rb:447:in `_run__1226739957950205446__process_action__742106135127651722__callbacks'
activesupport (3.0.7) lib/active_support/callbacks.rb:410:in `_run_process_action_callbacks'
activesupport (3.0.7) lib/active_support/callbacks.rb:94:in `run_callbacks'
actionpack (3.0.7) lib/abstract_controller/callbacks.rb:17:in `process_action'
actionpack (3.0.7) lib/action_controller/metal/instrumentation.rb:30:in `block in process_action'
activesupport (3.0.7) lib/active_support/notifications.rb:52:in `block in instrument'
activesupport (3.0.7) lib/active_support/notifications/instrumenter.rb:21:in `instrument'
activesupport (3.0.7) lib/active_support/notifications.rb:52:in `instrument'
actionpack (3.0.7) lib/action_controller/metal/instrumentation.rb:29:in `process_action'
actionpack (3.0.7) lib/action_controller/metal/rescue.rb:17:in `process_action'
actionpack (3.0.7) lib/abstract_controller/base.rb:119:in `process'
actionpack (3.0.7) lib/abstract_controller/rendering.rb:41:in `process'
actionpack (3.0.7) lib/action_controller/metal.rb:138:in `dispatch'
actionpack (3.0.7) lib/action_controller/metal/rack_delegation.rb:14:in `dispatch'
actionpack (3.0.7) lib/action_controller/metal.rb:178:in `block in action'
actionpack (3.0.7) lib/action_dispatch/routing/route_set.rb:62:in `call'
actionpack (3.0.7) lib/action_dispatch/routing/route_set.rb:62:in `dispatch'
actionpack (3.0.7) lib/action_dispatch/routing/route_set.rb:27:in `call'
rack-mount (0.6.14) lib/rack/mount/route_set.rb:148:in `block in call'
rack-mount (0.6.14) lib/rack/mount/code_generation.rb:93:in `block in recognize'
rack-mount (0.6.14) lib/rack/mount/code_generation.rb:68:in `optimized_each'
rack-mount (0.6.14) lib/rack/mount/code_generation.rb:92:in `recognize'
rack-mount (0.6.14) lib/rack/mount/route_set.rb:139:in `call'
actionpack (3.0.7) lib/action_dispatch/routing/route_set.rb:493:in `call'
sass (3.1.1) lib/sass/plugin/rack.rb:54:in `call'
actionpack (3.0.7) lib/action_dispatch/middleware/best_standards_support.rb:17:in `call'
actionpack (3.0.7) lib/action_dispatch/middleware/head.rb:14:in `call'
rack (1.2.2) lib/rack/methodoverride.rb:24:in `call'
actionpack (3.0.7) lib/action_dispatch/middleware/params_parser.rb:21:in `call'
actionpack (3.0.7) lib/action_dispatch/middleware/flash.rb:182:in `call'
actionpack (3.0.7) lib/action_dispatch/middleware/session/abstract_store.rb:149:in `call'
actionpack (3.0.7) lib/action_dispatch/middleware/cookies.rb:302:in `call'
activerecord (3.0.7) lib/active_record/query_cache.rb:32:in `block in call'
activerecord (3.0.7) lib/active_record/connection_adapters/abstract/query_cache.rb:28:in `cache'
activerecord (3.0.7) lib/active_record/query_cache.rb:12:in `cache'
activerecord (3.0.7) lib/active_record/query_cache.rb:31:in `call'
activerecord (3.0.7) lib/active_record/connection_adapters/abstract/connection_pool.rb:354:in `call'
actionpack (3.0.7) lib/action_dispatch/middleware/callbacks.rb:46:in `block in call'
activesupport (3.0.7) lib/active_support/callbacks.rb:416:in `_run_call_callbacks'
actionpack (3.0.7) lib/action_dispatch/middleware/callbacks.rb:44:in `call'
rack (1.2.2) lib/rack/sendfile.rb:107:in `call'
actionpack (3.0.7) lib/action_dispatch/middleware/remote_ip.rb:48:in `call'
actionpack (3.0.7) lib/action_dispatch/middleware/show_exceptions.rb:47:in `call'
railties (3.0.7) lib/rails/rack/logger.rb:13:in `call'
rack (1.2.2) lib/rack/runtime.rb:17:in `call'
activesupport (3.0.7) lib/active_support/cache/strategy/local_cache.rb:72:in `call'
rack (1.2.2) lib/rack/lock.rb:11:in `block in call'
<internal:prelude>:10:in `synchronize'
rack (1.2.2) lib/rack/lock.rb:11:in `call'
actionpack (3.0.7) lib/action_dispatch/middleware/static.rb:30:in `call'
railties (3.0.7) lib/rails/application.rb:168:in `call'
railties (3.0.7) lib/rails/application.rb:77:in `method_missing'
railties (3.0.7) lib/rails/rack/log_tailer.rb:14:in `call'
rack (1.2.2) lib/rack/content_length.rb:13:in `call'
rack (1.2.2) lib/rack/handler/webrick.rb:52:in `service'
/Users/helixed/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/webrick/httpserver.rb:111:in `service'
/Users/helixed/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/webrick/httpserver.rb:70:in `run'
/Users/helixed/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/webrick/server.rb:183:in `block in start_thread'
编辑:好的,我发现了另一个问题,它与你的基本相同。他接受的答案表明你需要这样做:
class Session < Authlogic::Session::Base
authenticate_with User
end
class User < ActiveRecord::Base
acts_as_authentic do |c|
c.session_class = Session
c.find_by_login_method :find_by_username_or_email
end
end
在这里可以找到实现多登录字段身份验证的好方法。
为了防止链接被破坏,Michael Cindric在他的博客中建议如下(经过编辑以使用类和字段的名称):
class Session < Authlogic::Session::Base
find_by_login_method :find_by_username_or_email
end
class User < ActiveRecord::Base
def self.find_by_username_or_email(login)
find_by_username(login) || find_by_email(login)
end
end