2011-09-09 16 views
6

Sto usando Railscast Episode # 250 per implementare l'autenticazione da zero. Tuttavia, ora voglio implementare il login di Facebook. Da googling ho trovato che OmniAuth e mettere a punto sono i contendenti principali per fare questo in RailsIntegrazione login di facebook con omniauth su binari

Tuttavia, questa pagina di esempio mi confonde: https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview

Essa afferma:

Con Rails 3.0. 3, utilizzare questo nella vostra Gemfile invece se rotaie sta avendo problemi a carico della porzione centrale OAuth:

gioiello "omniauth"

Successivamente, necessario dichiarare il provider nella vostra config/inizializzatori/devise.rb:

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

Domanda

Sono omniauth e mettere a punto interelated?

Cosa devo fare per implementare Facebook login nel mio autenticazione basata su Railscast 250

risposta

8

Nel vostro caso specifico si può pensare che meditano consente all'applicazione di autenticare gli utenti utilizzando un modulo (es: utilizzando una e-mail e password) o un token di autenticazione, Omniauth consente alla tua applicazione di "parlare" ai server di Facebook per autenticare un utente. In altre parole, Omniauth si trova in cima a Devise e estende il numero di modi in cui l'utente può autenticarsi.

Per implementare Facebook Login è necessario:

0) configurare devise: basta seguire questo: https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview

1) esporre un link nella vista che se cliccato dall'utente dirà Omniauth per iniziare " parlando "al server di Facebook.

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

2) A un certo punto il server di Facebook vi chiamerà applicazione in modo da avere per implementare un controller di rispondere a 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 

Ora si noterà che io chiamo un User.create_user (registration_hash). Questa implementazione del metodo dipenderà da come la vostra applicazione creare un utente, ma al minimo il metodo deve creare un utente e assegnare una password casuale:

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 

Nota: Il mio login supporto app con altro servizio così ho implementato una tabella che contiene token di autenticazione.

Spero che questo possa farti iniziare.

+0

L'opzione 'dialogo' sembra essere deprecato. Penso che "popup" sia l'equivalente in questi giorni. – drewww

+0

Ora, anche Popup è ammortizzato @drewww –