让 Rails 3.1 的 has_secure_password 与 OmniAuth 良好配合

发布于 12-05 18:43 字数 268 浏览 1 评论 0原文

我正在将一个项目从 Rails 3 移植到 3.1。我的身份验证系统很容易切换到 ActiveRecord 中新的 has_secure_password。我遇到的唯一问题是我也使用 OmniAuth,并且我已经设置了系统,因此如果用户使用 OmniAuth 提供商之一进行注册,则帐户不应需要密码。我似乎无法覆盖 has_secure_password 的password_digest 验证设置。是否有办法关闭这些验证并编写我自己的验证,或者我是否必须使用我的 Rails 3 版本站点中的旧手写 bcrypt 函数?

I'm porting a project from Rails 3 to 3.1. My authentication system was easily switched over to the new has_secure_password in ActiveRecord. The only problem I'm running into is that I also use OmniAuth and I have the system set up so if a user signs up using one of the OmniAuth providers the account shouldn't require a password. I can't seem to override the password_digest validations setup by has_secure_password. Is there anyway to turn off those validations and write my own, or am I going to have to just use my old hand written bcrypt functions from my Rails 3 version of the site?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

醉城メ夜风2024-12-12 18:43:54

我最终又回到使用自定义方法。然而,我后来确实意识到,我应该能够使用 before_validation 回调来检查条件,然后如果它们匹配,则将 password_digest 设置为任何简单的内容,例如“0”。这样,摘要就永远不会为空,但同时它不应该被验证为正确的密码,从而使他们通过 OmniAuth 登录。

如果我错了,请随时纠正我。

I ended up going back to using custom methods. However, I did realize afterwards that I should've been able to use a before_validation callback to check the conditions, then if they matched set the password_digest to anything simple like '0'. This way the digest would never be blank, but at the same time it shouldn't ever validate as a correct password, making them sign in through OmniAuth.

Feel free to correct me if I'm mistaken.

長街聽風2024-12-12 18:43:54

斯科特,你的想法是正确的。我一直在努力解决这个问题,但没有成功。我尝试覆盖“has_secure_password”,但它根本不起作用。不管我把代码粘在哪里。

相反,我有以下内容:

class User < ActiveRecord::Base
  has_secure_password

  validates_presence_of :password, :on => :create, :if => :password_required

  # Associations
  has_many :authentications

  # Callbacks
  before_validation :no_password_omniauth

  # Gets set to true if the caller is trying to authenticate with omniauth.
  @called_omniauth = false

  # Build new omniauth users
  def apply_omniauth(omniauth)
    authentications.build(
    :provider => omniauth['provider'], 
    :uid => omniauth['uid'])
    self.first_name = omniauth['user_info']['first_name'] if self.first_name.blank?
    self.last_name = omniauth['user_info']['last_name'] if self.last_name.blank?
    self.email = omniauth['user_info']['email'] if omniauth['user_info']['email'] && self.email.blank?
    @called_omniauth = true
  end

  def password_required
    return false if @called_omniauth == true
    (authentications.empty? || !password.blank?)
  end

  private

  def no_password_omniauth
    self.password_digest = 0 unless password_required
  end

end

当有人尝试进行身份验证或注册时,从控制器调用 apply_omniauth 方法。

感谢您提出的想法。

Scott, your idea is correct. I've been wrestling with this problem to no avail. I tried to override 'has_secure_password' and it simply won't work. No matter where I stuck the code.

Instead I have the following:

class User < ActiveRecord::Base
  has_secure_password

  validates_presence_of :password, :on => :create, :if => :password_required

  # Associations
  has_many :authentications

  # Callbacks
  before_validation :no_password_omniauth

  # Gets set to true if the caller is trying to authenticate with omniauth.
  @called_omniauth = false

  # Build new omniauth users
  def apply_omniauth(omniauth)
    authentications.build(
    :provider => omniauth['provider'], 
    :uid => omniauth['uid'])
    self.first_name = omniauth['user_info']['first_name'] if self.first_name.blank?
    self.last_name = omniauth['user_info']['last_name'] if self.last_name.blank?
    self.email = omniauth['user_info']['email'] if omniauth['user_info']['email'] && self.email.blank?
    @called_omniauth = true
  end

  def password_required
    return false if @called_omniauth == true
    (authentications.empty? || !password.blank?)
  end

  private

  def no_password_omniauth
    self.password_digest = 0 unless password_required
  end

end

The apply_omniauth method gets called from the controller when someone is trying to authenticate or sign up.

Thanks for the idea you nailed it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文