【发布时间】:2011-07-11 17:53:06
【问题描述】:
我正在尝试使用 Devise 来布局 Rails 应用程序以进行身份验证。我想要一个初始登录页面,人们可以在其中输入电子邮件地址。我想在获得电子邮件地址后立即创建一个帐户,然后让用户稍后完成身份验证过程。是否有一些文档可以显示如何执行此操作?
谢谢!
【问题讨论】:
标签: ruby-on-rails-3 authentication devise
我正在尝试使用 Devise 来布局 Rails 应用程序以进行身份验证。我想要一个初始登录页面,人们可以在其中输入电子邮件地址。我想在获得电子邮件地址后立即创建一个帐户,然后让用户稍后完成身份验证过程。是否有一些文档可以显示如何执行此操作?
谢谢!
【问题讨论】:
标签: ruby-on-rails-3 authentication devise
我最终通过使用“devise_invitable”gem 解决了这个问题。为了使这项工作正常进行,我必须扩展的唯一一件事是确保用户不需要经过身份验证即可发送邀请。覆盖邀请控制器,它工作得很好:
class InvitationsController < Devise::InvitationsController
include Devise::Controllers::InternalHelpers
skip_filter :authenticate_inviter!
skip_filter :authenticate!
def current_inviter
@current_inviter ||= User.new(params[:user])
end
end
【讨论】:
我不确定是否有很好的文档说明如何执行此操作,但这并不难。只是不需要在您的登录页面或该页面上登录表单的帖子上进行身份验证。在登录表单中收集电子邮件地址。向用户发送邮件到他们登录时使用的地址。在电子邮件中,包含“忘记密码”链接(重命名为“单击此处登录”......或其他)以强制用户登录并选择密码。这对你有用吗,还是我错过了什么?
【讨论】:
我意识到这已经晚了,但这可能对其他人有所帮助。我和你有类似的要求。基本上,我想让用户输入电子邮件地址,并将用户作为访客保留。将用户提升为“普通”用户后,我将重新启用密码身份验证。首先,我基于devise-gullible gem 创建了一个守望者策略。我对authenticate方法做了修改:
class Guest < Authenticatable
def authenticate!
resource = mapping.to.find_for_database_authentication(authentication_hash)
if resource
if resource.respond_to?(:guest?) and resource.guest?
success!(resource)
else
fail(:regular_user)
end
else
fail(:invalid)
end
end
end
我在我的用户模型中定义了一个访客用户,如下所示:
def guest?
self.roles.length == 0
end
我正在使用带有设计和 HABTM 的 CanCan 来处理角色。目前,我有一个“普通”用户和一个“管理员”用户。如果用户尚未分配角色,则该用户是访客。
然后,您需要覆盖设计注册控制器:
class Users::RegistrationsController < Devise::RegistrationsController
prepend_before_filter :allow_params_authentication!, :only => :create
def create
resource = warden.authenticate(:guest,
{ scope: resource_name,
recall: "#{controller_path}#new" })
if resource
set_flash_message(:notice, :signed_in) if is_navigational_format?
sign_in(resource_name, resource)
respond_with resource, :location => after_sign_in_path_for(resource)
elsif warden.winning_strategy.message == :regular_user
set_flash_message :notice, :regular_user if is_navigational_format?
redirect_to new_session_path(resource_name)
else
super
end
end
end
请注意,这个想法是我们尝试仅对运行访客策略的用户进行身份验证。如果他已经注册为访客,只需正常登录即可。如果访客策略因为他已注册而失败,但现在是普通用户,则重定向到正常登录页面。
现在可以保留我可能希望从客人那里收集的一些有限信息,而不要求他必须进行完整的注册。我使用普通的用户模型:
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable, :confirmable,
:recoverable, :rememberable, :trackable, :omniauthable,
:token_authenticatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me
has_and_belongs_to_many :roles
def self.new_with_session(params, session)
super.tap do |user|
if user.password.blank?
user.password = Devise.friendly_token[0,31]
# Also, we don't need to do email confirmation in this case.
# The user will have the guest role, and we'll do a confirmation
# when we promote him to a 'regular' user.
user.skip_confirmation!
end
end
end
def has_role?(role)
!!self.roles.find_by_name(role.to_s.camelize)
end
end
请注意,我在build_with_session 中自动生成密码。您可以在您选择的时候发送一个身份验证令牌,然后要求用户在那个时候设置一个新密码。然后,您还需要更改他的角色,以便他成为普通用户(或做任何您想要说明他不再是客人的事情)。
这是我在首页上显示的部分内容:
<%= simple_form_for(resource,
as: resource_name,
url: user_registration_path,
defaults: { required: false },
html: { class: 'well' },
wrapper: :bootstrap,
validate: true) do |f| %>
<%= f.error_notification %>
<fieldset>
<legend>New here? Let's get started!</legend>
<%= f.input :email, placeholder: 'user@example.com', validate: { uniqueness: false } %>
<%= f.button :submit, "Get my quote!", class: 'btn-primary' %>
</fieldset>
<% end %>
因此,此表单既可用作访客注册表单,也可用作登录表单。到目前为止,我真正关心的唯一想法是注册控制器正在处理身份验证,但我没有看到解决此问题的直接方法。
我在我的本地 lib 目录中实施了这个策略。请务必正确设置加载路径,并将require 'devise_guest' 添加到config/initializers/devise.rb。
【讨论】: