【问题标题】:Rails 4 Facebook authentication with Devise and OmniauthRails 4 Facebook 身份验证与 Devise 和 Omniauth
【发布时间】:2016-02-26 20:01:32
【问题描述】:

我正在尝试在我的应用中为客户模型实施来自 Facebook 的身份验证。我已经使用 Devise 对客户进行了身份验证。 我关注了this guide。 在初始化器 devise.rb 我添加了这一行:

config.omniauth :facebook, ENV['FACEBOOK_KEY'], ENV['FACEBOOK_SECRET'], scope: "email"

这是我的客户模型:

class Customer < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable, :omniauthable,
     :recoverable, :rememberable, :trackable #, :validatable

validates_presence_of :name

validates_uniqueness_of :nickname

before_save :complete_nickname

def complete_nickname
  if !self.nickname?
    self.nickname = self.email
  end
end

def facebook
  identities.where( :provider => "facebook" ).first
end

def facebook_client
  @facebook_client ||= Facebook.client( access_token: facebook.accesstoken )
end
end

这是我的身份模型,按照指南中的说明编写:

class Identity < ActiveRecord::Base
  belongs_to :customer

  validates_presence_of :uid, :provider
  validates_uniqueness_of :uid, :scope => :provider

  def self.find_for_oauth(auth)
    identity = find_by(provider: auth.provider, uid: auth.uid)
    identity = create(uid: auth.uid, provider: auth.provider) if identity.nil?
    identity.accesstoken = auth.credentials.token
    identity.refreshtoken = auth.credentials.refresh_token
    identity.name = auth.info.name
    identity.email = auth.info.email
    identity.nickname = auth.info.name.gsub(/\s+/, "")
    identity.image = auth.info.image
    identity.phone = auth.info.phone
    identity.urls = (auth.info.urls || "").to_json
    identity.save
    identity
  end
end

这是我的 OmniauthCallbackController

class OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def facebook
    generic_callback( 'facebook' )
  end

  def generic_callback( provider )
    @identity = Identity.find_for_oauth env["omniauth.auth"]

    @customer = @identity.customer || current_customer
    if @customer.nil?
      @customer = Customer.create( email: @identity.email || "", nickname: @identity.email || "" )
      @identity.update_attribute( :customer_id, @customer.id )
    end  

    if @customer.email.blank? && @identity.email
      @customer.update_attribute( :email, @identity.email)
    end

    if @customer.persisted?
      @identity.update_attribute( :customer_id, @customer.id )
      # This is because we've created the user manually, and Device expects a
      # FormUser class (with the validations)
      @customer = FormUser.find @customer.id
      sign_in_and_redirect @customer, event: :authentication
      set_flash_message(:notice, :success, kind: provider.capitalize) if is_navigational_format?
      else
        session["devise.#{provider}_data"] = env["omniauth.auth"]
        redirect_to new_customer_registration_url
      end
    end
  end

当我点击使用 Facebook 登录时,我未通过身份验证,应用程序将我重定向到登录表单。 在服务器输出上,我看到它尝试创建一个客户,但随后失败并回滚:

  SQL (0.3ms)  UPDATE "identities" SET "accesstoken" = $1, "updated_at" = $2 WHERE "identities"."id" = $3  [["accesstoken", "CAABtFtDqAlwBAEFzpAtw2W2gUTLkpKbtjI4lqKibkIO5kyJSwNYK9TDzDG4NfEoq40oQdUzXxZADRZBwYy319KPobEU6378ULwQ3PtKT46EbEugs4eIdsQyfZC3S8yLIJoPW6uq7ZAF0AnEeepDvl97ajbazsmGsuP22rnK0G1zSTHzoBfPpGZAD4NkgW7Kp5r5TiLhxxEgZDZD"], ["updated_at", "2015-11-24 11:18:28.010402"], ["id", 2]]
  (65.7ms)  COMMIT
  (0.2ms)  BEGIN
  Customer Exists (4.0ms)  SELECT  1 AS one FROM "customers" WHERE  "customers"."nickname" = '' LIMIT 1
  (0.2ms)  ROLLBACK

也许这是我在 Customer 对象上已有的验证控件,但我不知道它是什么。 这是我的客户的架构:

  create_table "customers", force: :cascade do |t|
    t.string   "email",                   default: "",   null: false
    t.string   "encrypted_password",      default: "",   null: false
    t.string   "name",                    default: "",   null: false
    t.string   "surname",                 default: "",   null: false
    t.string   "nickname",                default: "",   null: false
    ...
  end

有人可以帮助我吗?提前致谢

【问题讨论】:

  • 我认为我的问题是 Facebook 没有返回电子邮件,但我在设计初始化程序中将电子邮件指定为范围

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


【解决方案1】:

试试这个配置

设计.rb

config.omniauth :facebook, ENV['FACEBOOK_KEY'], ENV['FACEBOOK_SECRET'], scope: 'email', info_fields: 'email, name'

【讨论】:

  • 好的,谢谢!现在我有一个电子邮件!我在电子邮件和姓名之间放了一个空格,因为它不起作用。它还没有进行身份验证,但现在我有一个电子邮件地址
【解决方案2】:

我解决了,它似乎可以与我的 Facebook 帐户一起使用。 我用bundle update omniauth-facebook 更新了omniauth-facebook gem,这可能是问题的一部分。我以这种方式修改了初始化器 devise.rb(范围和 info_fields 中没有空格):

`config.omniauth :facebook, ENV['FACEBOOK_KEY'], ENV['FACEBOOK_SECRET'], scope: "email,public_profile", info_fields: 'email,name,first_name,last_name'`

并修改了OmniauthCallbackController:

@customer = Customer.create( email: @identity.email || "", nickname: @identity.nickname || "", 
  name: env["omniauth.auth"]["info"]["first_name"] || "", 
  surname: env["omniauth.auth"]["info"]["last_name"] || "",
  password: "********", password_confirmation: "********" )
  @identity.update_attribute( :customer_id, @customer.id )

因为在我的客户模型中,姓名和姓氏是必填字段。 我还是有问题。我在 Heroku 上推送了应用程序,我可以使用我的 Facebook 帐户和其他用户帐户登录,但对于其他一些用户,Facebook 不会返回电子邮件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-12
    • 2012-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多