【问题标题】:Rails devise omniauth facebookRails 设计了omniauth facebook
【发布时间】:2016-06-10 03:53:31
【问题描述】:

我无法让 devise omniauth-facebook 工作。我按照设计指南无济于事。我认为我的问题是模型没有检索信息。

型号

class User < ActiveRecord::Base
  has_attached_file :image, styles: {large: "1920x1080#", medium:              "800x500#", thumb: "100x100"}, :default_url =>    "/images/:style/missing.png"
  validates_attachment_content_type :image, :content_type =>    ["image/jpg", "image/jpeg", "image/png", "image/gif"]

  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :trackable, :validatable,
     :omniauthable, :omniauth_providers => [:facebook]
  def admin?
    admin
  end

  def self.from_omniauth(auth)
    where(provider: auth.provider, uid: auth.uid).first_or_create do     |user|
      user.email = auth.info.email
      user.password = Devise.friendly_token[0,20]
      user.name = auth.info.name   # assuming the user model has a     name
      user.image = auth.info.image # assuming the user model has an image
      puts request.env["omniauth.auth"]
    end
  end

  def self.new_with_session(params, session)
    super.tap do |user|
      if data = session["devise.facebook_data"] &&     session["devise.facebook_data"]["extra"]["raw_info"]
        user.email = data["email"] if user.email.blank?
      end
    end
  end
end

Routes.rb

Rails.application.routes.draw do

  mount RailsAdmin::Engine => '/admin', as: 'rails_admin'

  devise_for :users do
    delete 'logout' => 'sessions#destroy', :as => :destroy_user_session,
    :controllers => { :omniauth_callbacks => "user/omniauth_callbacks" }
  end

控制器

class User::OmniauthCallbacksController <         Devise::OmniauthCallbacksController
  # You should configure your model like this:
  # devise :omniauthable, omniauth_providers: [:twitter]

  # You should also create an action method in this controller like this:
  # def twitter
  # end
  def facebook
    # You need to implement the method below in your model (e.g. app/models/user.rb)
    @user = User.from_omniauth(request.env["omniauth.auth"])
    if @user.persisted?
      sign_in_and_redirect @user, :event => :authentication #this will throw if @user is not activated
      set_flash_message(:notice, :success, :kind => "Facebook") if is_navigational_format?
    else
      session["devise.facebook_data"] = request.env["omniauth.auth"]
      redirect_to new_user_registration_url
    end
  end

  def self.new_with_session(params, session)
    if session["devise.user_attributes"]
      new(session[devise.user_attributes], without_protection: true) do |user|
        user.attributes = params
        user.valid?
      end
    else
      super
    end

点击“使用 facebook 登录”后,它会指向一个 facebook 网址,我输入密码,按 Enter,然后重定向到带有长网址的同一页面。 (http://localhost:3000/demographics?code=AQDK1z40APoLiWykomxDDUljBUNHotenM4lzj_bZMhH8iQ74J_Nu_EUnPqBqkbNAeWQEPZwQs7YghqkB4eD7AoQLkN_RuYIlmotMtrJc4UyGRSe3CJIHcxp6kcB9BuYHA_Ldz0NMJvvGzOuvC-uDpFn6TyrzvV5v9LvivORXVduSsCy7_r6PcW8jxAkWqZzKyASXf26h8h3f_kha2d0KX6Ygft8ozN1HT9Xr-1y7ZtIKgTXEGMrqK950kASv2oTE0tQ5CYt6mfEZsVyLpykYIApOls8NLhjOaOIJewzV9EnLdSq0FbrvtedhhDmy-hg6IkRAbRVgwEkfUFsi9DXoxKyX&state=bdbf498f33f67ef57f3f54b846f870f21bb80c039c099f1a#=)

编辑:

现在我得到了

Could not authenticate you from Facebook because "Invalid credentials".

【问题讨论】:

  • 我不知道如何记录错误。我将 binding.pry 放在控制器模型中,但它没有被触发。但是,在我的 omniauth_callbacks.rb 中,我将类 User 更改为类 Users,这解决了一个问题。你有没有机会帮我弄清楚如何调试?
  • 您是否使用您的 facebook 密钥和秘密凭据配置了您的 initializers/devise.rb
  • 是的,我在那里硬编码。 APPID 和 APPSECRET

标签: ruby-on-rails ruby ruby-on-rails-3 devise omniauth-facebook


【解决方案1】:

问题是 Facebook 并不总是为用户返回电子邮件

来自 Facebook 开发者https://developers.facebook.com/bugs/298946933534016

一些可能的原因:

  • 帐户中没有电子邮件地址
  • 帐户中没有确认的电子邮件地址
  • 帐户中没有经过验证的电子邮件地址
  • 用户输入了一个安全检查点,要求他们重新确认 他们的电子邮件地址,但他们还没有这样做
  • 用户的电子邮件地址无法访问

如果 request.env["omniauth.auth"].info.email.present 在你的控制器中设置一个条件?请参阅下面的脚本。

    class User::OmniauthCallbacksController < Devise::OmniauthCallbacksController
      def facebook
        puts request.env["omniauth.auth"]   #  check if request.env["omniauth.auth"] is provided an email
        if request.env["omniauth.auth"].info.email.present?
            @user = User.from_omniauth(request.env["omniauth.auth"])
            if @user.persisted?
              sign_in_and_redirect @user, :event => :authentication #this will throw if @user is not activated
              set_flash_message(:notice, :success, :kind => "Facebook") if is_navigational_format?
            else
              session["devise.facebook_data"] = request.env["omniauth.auth"]
              redirect_to new_user_registration_url
            end
        else
            redirect_to new_user_registration_url, notice: "Couldn't connect to your #{request.env["omniauth.auth"].provider} account. Try to sign up."
        end    
      end
    end

【讨论】:

    【解决方案2】:

    这对我有用:

    用户模型

    devise :omniauthable, :omniauth_providers => [:facebook]
    
    def self.from_omniauth(auth)
      where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
          user.provider = auth.provider
          user.uid = auth.uid
          user.email = auth.info.email
          user.username = auth.info.name #gives full user name
          user.password = Devise.friendly_token[0,20]
          user.skip_confirmation!
          user.save
        end
    end
    

    devise.rb

    config.omniauth :facebook, ENV['facebook_key'], ENV['facebook_secret'],
     scope: 'email,public_profile', info_fields: 'email, first_name, last_name'
    

    callbacks_controller.rb

    class CallbacksController < ApplicationController
      def facebook
        @user = User.from_omniauth(request.env["omniauth.auth"])
        if @user.persisted?
          sign_in_and_redirect @user, :event => :authentication
          flash[:notice] = "Logged in as #{@user.username}"      
        else
          session["devise.facebook_data"] = request.env["omniauth.auth"]
          redirect_to new_user_registration_url
        end
      end
    
      def failure
        redirect_to root_path
      end
    end
    

    routes.rb

    devise_for :users, controllers: { omniauth_callbacks: "callbacks" }
    

    【讨论】:

    • 谢谢,您能告诉我您是如何存储 ENV 变量的吗?目前,我的硬编码在 devise.rb 中。
    • config/application.yml 中我使用了figaro gem github.com/laserlemon/figaro
    • 谢谢!这真的很有帮助!
    【解决方案3】:

    所以问题是我没有正确配置路由。

    事实上,我不得不删除所有现有的设计路线并添加这一行。

    devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-02-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-23
      • 2012-03-05
      • 2017-11-14
      相关资源
      最近更新 更多