【问题标题】:Omniauth not responding to GET RequestOmniauth 未响应 GET 请求
【发布时间】:2014-07-28 21:46:26
【问题描述】:

我正在尝试为用户提供通过 Facebook 登录的选项。

我的身份验证由 Devise 管理,我正在使用 Omniauth-Facebook gem。

当我尝试在我的设计视图 (session/new.html.erb) 中通过 Facebook 登录用户时,用户已成功登录。

new.html.erb

<div><%= link_to image_tag('facebook_login.png'), user_omniauth_authorize_path(:facebook) %></div>

但是,当我尝试在不同的控制器中登录用户(使用与上面完全相同的代码)时,页面并没有真正响应,并且我的日志中出现以下请求:

Started GET "/users/auth/facebook" for 127.0.0.1 at 2014-06-07 21:14:41 -0300
I, [2014-06-07T21:14:41.311370 #4592]  INFO -- omniauth: (facebook) Request phase initiated. 

Devise 是否只允许用户通过单个控制器使用 facebook 登录,还是我需要对 link_to 路径进行一些其他更改?

【问题讨论】:

  • 看起来很奇怪。你添加了 Omniauth 回调控制器吗?

标签: ruby-on-rails devise omniauth


【解决方案1】:

我认为您将omniauth 与devise 分开配置(在omniauth 初始化程序中),但仍然使用devise 进行登录(为omniauth 设计路径)。

我留下了让它与设计工作流程一起工作的步骤

宝石文件

gem 'devise'
gem 'omniauth-facebook'

config/initializers/devise.rb

//add this for tell devise the omniauth configuration for facebook
config.omniauth :facebook, ENV['FACEBOOK_APP_ID'], ENV['FACEBOOK_SECRET']

config/enviroments/development.rb

//your secrets for development, is useful have it this way because you can use different applications for your rails enviroments
ENV['FACEBOOK_APP_ID'] = 'xxxxxxxxxxx';
ENV['FACEBOOK_SECRET'] = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';

routes.rb

//override the controller for omniauth callbacks, we will define this later, this is our custom behavior for dealing with what omniauth hash will return to us
devise_for :users, controllers: { omniauth_callbacks: "users/omniauth_callbacks" }

好的,这是基本的,现在我们需要自定义回调来定义如何处理 facebook 提供给我们的信息。

我没有这方面的工作示例,我的回调实际上非常复杂,因为有很多行为,但我会尝试通过记忆来解释。

Facebook 和所有omniauth 策略都会返回一个uid,我们将通过provider 和他的uid 来识别我们的用户( user id),所以我们要将此参数添加到我们的用户模型并进行相应的迁移,这些都是字符串

rails g migration AddOmniauthToUsers uid provider
rake db:migrate

下一步是配置我们的omniauth回调

controllers/users/omniauth_callbacks_controller.rb (注意在新的用户文件夹中)

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  //this inheritance from Devise::OmniauthCallbacks so we will have all his methods 

  #uncomment the next line to see the hash from facebook, utile for debugging to see if we are getting a connection to facebook or not.
  #raise request.env["omniauth.auth"].to_yaml
  def all
    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
       flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => user.provider.titleize
    else
        session["devise.user_attributes"] = request.env["omniauth.auth"] #create a cookie with omniauth hash to give it another try, for example in a already register email
       redirect_to new_user_registration_url
    end 
  end

  //alias method is for have the same method for various strategies(google, twitter, etc)
  alias_method :facebook, :all
end

基本上,当我们点击 facebook 连接时,我们会得到这个带有所有omniauth 参数的散列 request.env["omniauth.auth"],现在我们需要定义我们的 from_omniauth 在我们的用户模型

中处理的方法

models/user.rb

def self.from_omniauth(auth)
  where(auth.slice(:provider, :uid)).first_or_create do |user|
    user.provider = auth.provider
    user.uid = auth.uid
    user.email = auth.info.email
  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
end

def password_required?
  super && self.provider.blank?
end

def update_with_password(params, *options)
  if encrypted_password.blank?
    update_attributes(params, *options)
  else
    super
  end
end

def has_no_password?
  self.encrypted_password.blank?
end

这里我们有 4 个新方法,from_omniauth 将使用哈希中的omniauth 参数创建一个新用户(您可以在omniauth facebook gem 中查看facebook 的omniauth 哈希),在这里你应该保存另一个值,比如 image_link 或 username 如果你有你的用户模型,我想从这里调用另一个模型 user_profile 与所有这些数据试图留下他自己的东西。

接下来我们有一个新的会话,它使用我们保存的 cookie 的内容,以防我们的回调发生错误

password_required?update_with_password 都是我们需要重写的设计方法,这个方法抓住了我们在具有omniauth 提供程序且未定义密码的情况下的新行为,您可以在您的表单中使用 has_no_password? 以在需要时显示密码字段(在没有密码的情况下更新用户属性)。

我希望它有所帮助,当您了解工作流程非常容易自定义行为时,但遗憾的是大多数指南只允许您复制粘贴代码。

【讨论】:

  • 感谢所有帮助。然而问题是我有一个干扰 jquery_ujs 的脚本。一旦我从资产中删除了脚本,链接就可以正常工作了。
猜你喜欢
  • 2021-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-17
  • 2014-09-01
相关资源
最近更新 更多