2012-11-02 26 views
6

Tôi có một số xác nhận mật khẩu cho mô hình User của tôi, và một phương pháp create_with_omniauth để có được thông tin từ tài khoản Facebook của người dùng:Làm cách nào để bỏ qua xác thực mật khẩu trong phương thức đăng nhập OmniAuth sau đây?

user.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+\-.][email protected][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 

Bây giờ khi tôi bấm link_to "Sign in with Facebook, "auth/facebook" tôi nhận được lỗi này:

Validation failed: Password can't be blank, Password can't be blank, Password is too short (minimum is 6 characters), Password confirmation can't be blank

Vì hai dòng này trong số User mô hình:

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

Làm cách nào để bỏ qua xác thực đó khi người dùng đang cố gắng đăng nhập bằng phương thức đăng nhập OmniAuth?

Trả lời

17

Điều này có thể được thực hiện theo 2 cách.

1) Chỉ cần lưu số ngẫu nhiên được tạo an toàn trong trường mật khẩu (tốt hơn vì dễ dàng và duy trì tính nhất quán) cá nhân tôi đã áp dụng phương pháp này vì người dùng đã đăng nhập qua trang web xã hội sẽ không đăng nhập thông qua trang web đăng nhập.

2) Hoặc sử dụng một 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? 

Bất cứ khi nào đăng nhập thông qua bất kỳ trang web xã hội chỉ làm lĩnh vực này thành sự thật. Tôi theo phương pháp thứ hai sau đó quay sang giải pháp đầu tiên vì nó tốt hơn.

Cá nhân tôi đề nghị bạn đi cho phương pháp đầu tiên

+0

Xin cảm ơn các đề xuất! Xin lỗi, tôi là người mới bắt đầu Rails. Bạn có thể cho tôi một ví dụ về mã để tạo mật khẩu ngẫu nhiên khi người dùng nhấp vào đăng nhập Facebook không? – alexchenco

+0

self.password = self.password_confirmation = SecureRandom.urlsafe_base64 (n = 6) –

+0

Cảm ơn! Vì vậy, nên đi trong phương pháp 'self.create_with_omniauth'? Chẳng phải nó sẽ là 'user.password'? – alexchenco

1

Giải pháp của tôi cho điều này là để thêm một mật khẩu đơn giản để omniauth người dùng, và làm cho nó không thể đăng nhập bằng những mật khẩu nếu Rails phát hiện rằng họ là người dùng omniauth. Điều này đơn giản hóa mô hình Người dùng của tôi vì tôi vẫn có thể sử dụng has_secure_password và làm cho mật khẩu không liên quan (và không thể sử dụng) nếu họ sử dụng thông tin đăng nhập xã hội.

bảng cơ sở dữ liệu tài khoản của tôi có như sau:

  • tên
  • email
  • mật khẩu
  • password_confirmation
  • uid cung cấp

sessions_controller.rb

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

sessions_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 
+0

chỉ dành cho người có thể cần điều này, nếu bạn đang sử dụng has_secure_password và bạn có xác nhận mật khẩu thì bạn phải cung cấp mật khẩu. Điều này làm việc cho tôi khi tôi sử dụng ma thuật omniauth google oauth2. –

2

Như @Aayush gợi ý để tạo ra một lĩnh vực để phát hiện đăng nhập xã hội, sau đó thay vì tạo xác nhận riêng của bạn, bạn có thể ghi đè lên phương pháp devise này:

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

trong mẫu của bạn e.g User

Các vấn đề liên quan