2011-09-09 39 views
6

Tôi đang sử dụng Railscast Episode # 250 để triển khai xác thực từ đầu. Tuy nhiên, bây giờ tôi muốn thực hiện đăng nhập Facebook. Từ googling tôi đã phát hiện ra rằng OmniAuth và lập mưu là những ứng cử viên hàng đầu để làm điều này trong RailsTích hợp đăng nhập facebook với omniauth trên đường ray

Tuy nhiên, trang ví dụ này là khó hiểu với tôi: https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview

Nó nói:

Với Rails 3.0. 3, sử dụng này trong Gemfile của bạn thay vì nếu đường ray là có rắc rối tải oauth lõi:

gem "omniauth"

Tiếp theo, bạn cần phải khai báo các nhà cung cấp trong bạn config/initializers/devise.rb:

config.omniauth: facebook, "APP_ID", "APP_SECRET"

Câu hỏi

Are omniauth và đưa ra tương quan?

Tôi nên làm gì để thực hiện Facebook đăng nhập trong thẩm định của tôi dựa trên railscast 250

Trả lời

8

Trong trường hợp cụ thể của bạn, bạn có thể nghĩ rằng lập mưu cho phép ứng dụng của bạn để xác thực người dùng sử dụng một hình thức (ví dụ: bằng cách sử dụng một email và mật khẩu) hoặc mã thông báo xác thực, Omniauth cho phép ứng dụng của bạn "nói" với máy chủ Facebook để xác thực người dùng. Nói cách khác, Omniauth nằm trên đầu trang của Devise và mở rộng số cách người dùng của bạn có thể xác thực.

Thực hiện Facebook đăng nhập bạn cần phải:

0) configure devise: chỉ cần làm theo này: https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview

1) tiếp xúc với một liên kết trong quan điểm của bạn mà khi nhấn vào bởi người sử dụng sẽ cho Omniauth để bắt đầu " nói "với máy chủ Facebook.

=link_to image_tag("facebook_64.png", :size => "64x64", :alt => "Facebook"), user_omniauth_authorize_path(:facebook, :display=>"dialog"), :title=>"Facebook" 

2) Tại một thời điểm máy chủ Facebook sẽ gọi cho bạn ứng dụng vì vậy bạn phải thực hiện một bộ điều khiển để đáp ứng với Facebook

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController 
    before_filter { @omniauth_hash = env["omniauth.auth"] } 

     # This method is responsible to create a registration_hash given an 
     # omniaauth_hash 
     # schama: https://github.com/intridea/omniauth/wiki/Auth-Hash-Schema 
     def self.build_registration_hash(omniauth_hash={}) 
     if (omniauth_hash["provider"].downcase.eql?("facebook")) 
      provider = "facebook" 
      # catch any excpetions thrown by code just to make sure we can continue even if parts of the omnia_has are missing 
      begin 
      first_name = omniauth_hash['user_info']['first_name'] 
      last_name = omniauth_hash['user_info']['last_name'] 
      sex  = omniauth_hash.fetch('extra', {}).fetch('user_hash',{})['gender'] 
      birthday = Date.strptime(omniauth_hash.fetch('extra', {}).fetch('user_hash', {})['birthday'],'%m/%d/%Y') if omniauth_hash.fetch('extra', {}).fetch('user_hash', {})['birthday'] 
      if omniauth_hash.fetch('extra', {}).fetch('user_hash', {})['timezone'] 
       utc_offset_in_hours = (omniauth_hash.fetch('extra', {}).fetch('user_hash', {})['timezone']).to_i 
       time_zone = (ActiveSupport::TimeZone[utc_offset_in_hours]).name 
      else 
       time_zone = nil 
      end 
      locale = omniauth_hash.fetch('extra', {}).fetch('user_hash', {})['locale'] 
      home_town = omniauth_hash.fetch('extra', {}).fetch('user_hash', {}).fetch('location', {})['name'] 
      if omniauth_hash.fetch('user_info', {})['image'] 
       photo_url = (omniauth_hash.fetch('user_info', {})['image']).gsub("=square","=large") #http://graph.facebook.com/531564247/picture?type=square 
      else 
       photo_url = nil 
      end 
      rescue => ex 
      logger.error("Error while parsing facebook auth hash: #{ex.class}: #{ex.message}") 
      sex  = nil 
      birthday = nil 
      time_zone = nil 
      locale = nil 
      home_town = nil 
      photo_url = nil 
      end 
     elsif omniauth_hash['uid'].downcase.include?("google.com") 
      provider = "google" 
      if omniauth_hash['user_info']['first_name'] and omniauth_hash['user_info']['last_name'] 
      first_name = omniauth_hash['user_info']['first_name'] 
      last_name = omniauth_hash['user_info']['last_name'] 
      elsif omniauth_hash['user_info']['name'] 
      first_name = omniauth_hash['user_info']['name'].split(' ')[0] 
      last_name = omniauth_hash['user_info']['name'].split(' ')[1] 
      else 
      first_name = nil 
      last_name = nil 
      end 
      sex  = nil 
      birthday = nil 
      time_zone = nil 
      locale = nil 
      home_town = nil 
      photo_url = nil 
     elsif omniauth_hash['uid'].downcase.include?("yahoo.com") 
      provider = "yahoo" 
      if omniauth_hash['user_info']['first_name'] and omniauth_hash['user_info']['last_name'] 
      first_name = omniauth_hash['user_info']['first_name'] 
      last_name = omniauth_hash['user_info']['last_name'] 
      elsif omniauth_hash['user_info']['name'] 
      first_name = omniauth_hash['user_info']['name'].split(' ')[0] 
      last_name = omniauth_hash['user_info']['name'].split(' ')[1] 
      else 
      first_name = nil 
      last_name = nil 
      end 
      sex  = nil 
      birthday = nil 
      time_zone = nil 
      locale = nil 
      home_town = nil 
      photo_url = nil 
     elsif omniauth_hash['uid'].downcase.include?("aol.com") 
      if omniauth_hash['user_info']['first_name'] and omniauth_hash['user_info']['last_name'] 
      first_name = omniauth_hash['user_info']['first_name'] 
      last_name = omniauth_hash['user_info']['last_name'] 
      elsif omniauth_hash['user_info']['name'] 
      first_name = omniauth_hash['user_info']['name'].split(' ')[0] 
      last_name = omniauth_hash['user_info']['name'].split(' ')[1] 
      else 
      first_name = nil 
      last_name = nil 
      end 
      provider = "aol" 
      sex  = nil 
      birthday = nil 
      time_zone = nil 
      locale = nil 
      home_town = nil 
      photo_url = nil  
     else 
      provider = "open_id" 
      if omniauth_hash['user_info']['first_name'] and omniauth_hash['user_info']['last_name'] 
      first_name = omniauth_hash['user_info']['first_name'] 
      last_name = omniauth_hash['user_info']['last_name'] 
      elsif omniauth_hash['user_info']['name'] 
      first_name = omniauth_hash['user_info']['name'].split(' ')[0] 
      last_name = omniauth_hash['user_info']['name'].split(' ')[1] 
      else 
      first_name = nil 
      last_name = nil 
      end 
      sex  = nil 
      birthday = nil 
      time_zone = nil 
      locale = nil 
      home_town = nil 
      photo_url = nil 
     end 

     h = { 
      :provider => provider, 
      :email  => omniauth_hash['user_info']['email'], 
      :profile_attributes => { 
      :first_name => first_name , 
      :last_name => last_name, 
      :avatar_url => photo_url, 
      :sex  => sex, 
      :birthday => birthday, 
      :time_zone => time_zone, 
      :locale  => locale, 
      :location => home_town 
      } 
     } 
     end 

     def process_callback 

     # The registration hash isolates the rest of the code from learning all the different structures 
     # of the omnia_hash 
     registration_hash = Users::OmniauthCallbacksController.build_registration_hash(@omniauth_hash) 
     logger.debug(registration_hash.to_yaml) 

     # Set the @user to nil 
     @user = nil 

     # Find if an authentication token for this provider and user id already exists 
     authentication = Authentication.find_by_provider_and_uid(@omniauth_hash['provider'], @omniauth_hash['uid']) 
     if authentication  # We found an authentication 
      if user_signed_in? && (authentication.user.id != current_user.id) 
      flash[:error] = I18n.t "controllers.omniauth_callbacks.process_callback.error.account_already_taken", 
      :provider => registration_hash[:provider].capitalize, 
      :account => registration_hash[:email] 
      redirect_to edit_user_account_path(current_user) 
      return 
      end 
     else 
      # We could not find the authentication than create one 
      authentication = Authentication.new(:provider => @omniauth_hash['provider'], :uid => @omniauth_hash['uid']) 
      if user_signed_in? 
      authentication.user = current_user 
      else 
      registration_hash[:skip_confirmation] = true 
      authentication.user = User.find_by_email(registration_hash[:email]) || User.create_user(registration_hash) 
      end 
     end 

     @user = authentication.user 
     # save the authentication 
     authentication.token = @omniauth_hash 
     authentication.provider_name = registration_hash[:provider] 
     authentication.provider_username = registration_hash[:email] 

     if !authentication.save 
      logger.error(authentication.errors) 
     end 

     # If a user is signed in then he is trying to link a new account 
     if user_signed_in? 
      if authentication.persisted? # This was a linking operation so send back the user to the account edit page 
      flash[:success] = I18n.t "controllers.omniauth_callbacks.process_callback.success.link_account", 
            :provider => registration_hash[:provider].capitalize, 
            :account => registration_hash[:email] 
      else 
      flash[:error] = I18n.t "controllers.omniauth_callbacks.process_callback.error.link_account", 
            :provider => registration_hash[:provider].capitalize, 
            :account => registration_hash[:email], 
            :errors =>authentication.errors 
      end 
      redirect_to edit_user_account_path(current_user) 
     else 
      # This was a sign in operation so sign in the user and redirect it to his home page 
      if @user.persisted? && authentication.persisted? 
      flash[:success] = I18n.t "controllers.omniauth_callbacks.process_callback.success.sign_in", 
      :provider => registration_hash[:provider].capitalize, 
      :account => registration_hash[:email] 
      sign_in_and_redirect(:user,@user) 
      else 
      session['registration_hash'] = registration_hash 
      flash[:error] = I18n.t "controllers.omniauth_callbacks.process_callback.error.sign_in", 
      :provider => registration_hash[:provider].capitalize, 
      :account => registration_hash[:email] 

      redirect_to new_registration_users_url 

      end 
     end 
     end 

     def facebook 
     process_callback 
     end 

     def gmail 
     process_callback 
     end 

Bây giờ bạn sẽ thấy rằng tôi gọi một User.create_user (registration_hash). thực hiện phương pháp này sẽ phụ thuộc vào cách ứng dụng của bạn tạo một người dùng nhưng đồng tối thiểu phương pháp này phải tạo một người dùng và gán cho nó một mật khẩu ngẫu nhiên:

def self.create_user(registration_hash) 
    logger.info "Creating new user with registration hash: #{registration_hash.to_yaml}" 
    unless registration_hash or resigration_hash.empty? 
     return nil 
    end 
    user = User.new 
    user.email = registration_hash[:email] 
    if registration_hash[:password] 
     user.password = registration_hash[:password] 
    else 
     user.password = Devise.friendly_token[0,20] 
    end 
    user.password_confirmation = user.password 

    # custom app code here... 


    if registration_hash[:skip_confirmation] == true 
     user.confirm! 
    end 

    user  
    end 

Lưu ý: My hỗ trợ ứng dụng đăng nhập với dịch vụ khác vì vậy tôi có đã triển khai bảng chứa mã thông báo xác thực.

Hy vọng điều này có thể giúp bạn bắt đầu.

+0

Tùy chọn 'thoại' dường như bị phản đối. Tôi nghĩ 'popup' tương đương với những ngày này. – drewww

+0

Bây giờ, Popup cũng được khấu hao @drewww –

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