设计:创建没有密码的用户然后需要密码才能使用帐户?

时间:2011-07-11 17:53:06

标签: ruby-on-rails-3 authentication devise

我正在尝试使用Devise来布局Rails应用程序进行身份验证。我想有一个初始登陆页面,人们可以输入电子邮件地址。我想在收到电子邮件地址后立即创建一个帐户,然后让用户稍后完成身份验证过程。是否有一些文档可以说明如何做到这一点?

谢谢!

3 个答案:

答案 0 :(得分:7)

我最终通过使用“devise_invitable”宝石来解决这个问题。为了实现这一目标,我唯一需要扩展的是确保用户不需要通过身份验证来发送邀请。覆盖邀请函控制器并且它工作得很好:

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

答案 1 :(得分:3)

我不确定是否有关于如何做到这一点的良好文档,但这并不难。只是不要求在您的目标网页上或该页面上的登录表单上的帖子上进行身份验证。在登录表单中收集电子邮件地址。向用户发送邮件到他们登录的地址。在电子邮件中,包含“忘记密码”链接(重命名为“点击此处登录”......或其他)以强制用户登录并选择密码。这对你有用吗,还是我错过了什么?

答案 2 :(得分:3)

我意识到这已经很晚了,但这可能会对其他人有所帮助。我和你有类似的要求。基本上,我想让用户输入一个电子邮件地址,并将用户作为访客保留。一旦用户被提升为“常规”用户,我就重新启用密码身份验证。首先,我基于devise-gullible gem创建了一个warden策略。我对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

我正在使用CanCan with devise和HABTM来处理角色。目前,我有一个“常规”用户和一个“管理员”用户。如果用户尚未分配角色,则该用户是访客。

然后,您需要覆盖设计注册控制器:

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