2011-09-09 27 views
6

Estoy utilizando Railscast Episode # 250 para implementar la autenticación desde cero. Sin embargo, ahora quiero implementar el inicio de sesión en Facebook. De google he encontrado que OmniAuth y diseñar son los candidatos principales para hacer esto en los carrilesIntegrar el inicio de sesión de Facebook con omniauth en los rieles

Sin embargo, esta página ejemplo me confunde: https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview

Afirma:

Con Rails 3.0. 3, utilizar esto en su lugar si Gemfile rieles está teniendo problemas de carga del núcleo oauth:

joya "OmniAuth"

a continuación, que declarar el proveedor en su config/inicializadores/devise.rb:

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

Pregunta

son OmniAuth y diseñar interelacionado?

¿Qué debo hacer para implementar Facebook login en mi autenticación basado en Railscast 250

Respuesta

8

En su caso específico se puede pensar que maquinan permite a su aplicación para autenticar a los usuarios mediante un formulario (por ejemplo: mediante el uso de un correo electrónico y una contraseña) o un token de autenticación, Omniauth le permite a su aplicación "hablar" a los servidores de Facebook para autenticar a un usuario. En otras palabras, Omniauth se encuentra en la parte superior de Devise y extiende la cantidad de formas en que su usuario puede autenticarse.

Para implementar Facebook Tiene que:

0) Configurar legado: sólo tienes que seguir el siguiente: https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview

1) exponer un enlace en su opinión de que, cuando el usuario haga clic dirá OmniAuth para empezar " hablando "al servidor de Facebook.

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

2) En un momento el servidor de Facebook le llamará aplicación por lo que tiene que implementar un controlador para responder 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 

Ahora se dará cuenta de que yo llamo un User.create_user (registration_hash) Esta implementación del método dependerá de cómo su aplicación crear un usuario, pero al mínimo el método tiene que crear un usuario y asignarle una contraseña aleatoria:

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: Mi entrada apoyo aplicación con otro servicio, así que tengo implementó una tabla que contiene tokens de autenticación.

Espero que esto pueda comenzar.

+0

La opción 'diálogo' parece estar en desuso. Creo que 'popup' es el equivalente en estos días. – drewww

+0

Ahora, Popup también se depreció @drewww –

Cuestiones relacionadas