6

我对我的User模型进行了一些密码验证,以及create_with_omniauth从用户的 Facebook 帐户获取信息的方法:

用户.rb:

class User < ActiveRecord::Base
  attr_accessible :name, :email, :password, :password_confirmation

  has_secure_password

  validates :name, presence: true, length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, presence:   true,
                    format:     { with: VALID_EMAIL_REGEX },
                    uniqueness: { case_sensitive: false }
  validates :password, presence: true, length: { minimum: 6 }
  validates :password_confirmation, presence: true

  def self.create_with_omniauth(auth)
    create! do |user|
      user.provider = auth["provider"]
      user.uid = auth["uid"]
      user.name = auth["info"]["name"]
      user.email = auth["info"]["email"]
    end
  end
end

现在当我点击link_to "Sign in with Facebook, "auth/facebook"我得到这个错误:

验证失败:密码不能为空,密码不能为空,密码太短(最少6个字符),密码确认不能为空

由于User模型中的这两行:

 validates :password, presence: true, length: { minimum: 6 }
 validates :password_confirmation, presence: true

当用户尝试使用 OmniAuth 登录方法登录时,如何绕过该验证?

4

3 回答 3

19

这可以通过 2 种方式完成。

1)只需在密码字段中保存一个随机安全生成的数字(更好,因为它很容易并且保持一致性)我个人应用了这种方法,因为通过社交网站签名的用户不会通过网站登录登录。

2) 或者,使用attr_accesor

 :login_social (will be treated as boolean  
 validates :password, presence: true, length: { minimum: 6 }, :if => !login_social?
 validates :password_confirmation, presence: true, :if => :login_social?

每当通过任何社交网站登录时,只需将此字段设为 true。我遵循第二种方法,然后转向第一种解决方案,因为它更好。

我个人建议你选择第一种方法

于 2012-11-02T05:15:57.573 回答
4

正如@Aayush 建议创建一个字段来检测社交登录,那么您可以覆盖此设计方法,而不是创建自己的验证:

 def password_required?
     self.social_login? ? false : super
 end

在您的模型中,例如User

于 2015-11-18T06:36:33.873 回答
1

我对此的解决方案是为omniauth 用户添加一个简单的密码,如果Rails 检测到他们是omniauth 用户,则无法使用这些密码登录。这简化了我的用户模型,因为我仍然可以使用 has_secure_password,并且如果他们使用社交登录名,密码就会变得无关紧要(并且无法使用)。

我的用户数据库表有以下内容:

  • 姓名
  • 电子邮件
  • 密码
  • 确认密码
  • uid
  • 提供者

session_controller.rb

def create
  auth = request.env["omniauth.auth"]
  if auth
    sign_in_with_auth(auth)
  else
    sign_in_with_password
  end
end

session_helper.rb

def sign_in_with_auth(auth)
  user = User.find_by(uid: auth['uid'])
  if user
    #sign in the user
  else
    #create a user with any password.
    user = User.create! do |user|
      ...
      user.password = 'bojanglesicedtea'
      user.password_confirmation = 'bojanglesicedtea'
      user.provider = auth['provider']
    end
    #then sign in the user
  end
end

def sign_in_with_password
  user = User.find_by(email: params[:sessions][:email].downcase)
  if user == user.authenticate(params[:sessions][:password]) && user.provider.nil?
    #sign in the user
    #user.provider.nil? will be true only if it is not a social login user
  else
    #direct to error notification
  end
end
于 2013-08-16T19:25:34.980 回答