“未找到。身份验证通道。”错误。设计 Omniauthable 模块在另一个引擎中时不起作用

Posted

技术标签:

【中文标题】“未找到。身份验证通道。”错误。设计 Omniauthable 模块在另一个引擎中时不起作用【英文标题】:"Not found. Authentication passthru." error. Devise Omniauthable module doesn't work when it's inside another engine 【发布时间】:2014-09-28 20:25:00 【问题描述】:

按照本指南,我尝试将 Devise 放入另一个可安装的 gem 中: How To: Use devise inside a mountable engine.

除了omniauth 部分外,一切似乎都运行良好。我正在努力让omniauth-google-oauth2 工作。我发现it's a known issue in Devise,但除了没有任何建议的解决方案有效之外,我注意到该问题中提到的解决方案has already been implemented inside Devise。

这是我到目前为止所做的:

my_engine/my_engine.gemspec

s.add_dependency 'omniauth'
s.add_dependency 'devise'
s.add_dependency 'omniauth-google-oauth2'

my_engine/lib/my_engine.rb

require 'omniauth-google-oauth2'
require 'devise'

my_engine/config/initializers/devise.rb

config.omniauth :google_oauth2, ENV['GOOGLE_OAUTH2_API_KEY'], ENV['GOOGLE_OAUTH2_SECRET'], scope: 'email, profile'

my_engine/config/routes.rb

devise_for :users, controllers: omniauth_callbacks: 'my_engine/omniauth_callbacks', class_name: "MyEngine::User", module: :devise

my_engine/app/controllers/my_engine/omniauth_callbacks_controller.rb

class MyEngine::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def all
    auth = request.env["omniauth.auth"]
    user = MyEngine::User.from_omniauth(request.env["omniauth.auth"])
    user.update_attributes(name: auth.info.name)
    if user.persisted?
      flash.notice = 'Signed in!'
      sign_in_and_redirect user
    else
      session["devise.user_attributes"] = user.attributes
      redirect_to new_user_registration_url
    end
  end
  alias_method :google_oauth2, :all
end

当我单击“使用 Google OAuth2 登录”时,它会直接转到 MyEngine::OmniauthCallbacksController#passthru 并输出“未找到。身份验证通路”。我一直在挖掘源代码,但我无法弄清楚 Devise 如何让它通过提供程序方法而不是 #passthru。我在这里错过了什么吗?我在 rails 4.1、Ruby 2.0、devise 3.2.4 和 omniauth-oauth2 1.2.0 上运行。

【问题讨论】:

我知道这听起来不像一个完整或完美的解决方案,但你不能向控制器添加一个 passthru 操作并处理其中的提供程序特定代码吗? 另外,你能告诉我们设计/omniauth相关路径的rake路由结果吗? 【参考方案1】:

我也有这个问题。我工作的版本与您链接到的 github 问题页面上讨论的解决方案非常相似,但不完全相同(我在下面的代码中稍微调整了我所做的,因为我在我的devise_for)。另外,我目前正在设计 3.1.2,但希望它与以下内容足够相似,可以为您工作。

my_engine/config/routes.rb

devise_for :users, :class_name => 'MyEngine::User', :module => :devise, :controllers =>  :omniauth_callbacks => "my_engine/omniauth_callbacks" 

devise_scope :user do
  # Had to add routes for callbacks here because otherwise the routes get
  # messed up -- prepending an extra "/my_engine" in one case.
  providers = Regexp.union(Devise.omniauth_providers.map(&:to_s))

  path_prefix = '/users/auth'

  match "#path_prefix/:provider",
    :constraints =>  :provider => providers ,
    :to => "omniauth_callbacks#passthru",
    :as => :user_omniauth_authorize,
    :via => [:get, :post]

  match "#path_prefix/:action/callback",
    :constraints =>  :action => providers ,
    :to => 'omniauth_callbacks',
    :as => :user_omniauth_callback,
    :via => [:get, :post]
end

my_engine/config/initializers/devise.rb

config.router_name = :my_engine
config.omniauth_path_prefix = "/my_engine/users/auth"

其中一些可能是不必要的,但是在我花了一些时间使用调试器逐步完成流程之后,我得到了它的工作方式,并且没有时间返回并尝试使其更优雅/精简或任何东西。

【讨论】:

我收到 Invalid route name, already in use: 'user_omniauth_authorize' 错误,因为 Devise 已经创建了路线。你是如何解决这部分问题的? 我没有收到那个错误!我认为这是因为我仍在使用 rails 3.2.19,并且我认为检查是作为 rails 4 的一部分添加的。将 skip: :omniauth_callbacks 添加到您的 devise_for 语句应该会阻止尝试的重复,因为它应该会阻止设计生成那些路线。 我尝试将skip: :omniauth_callbacks 添加到我的devise_for 并且我的fb 登录流程停止工作!我必须在我的my_engine\initializers\devise.rb 中的最后一个end 之前添加Rails.application.config.after_initialize do ::OmniAuth::config.path_prefix = config.omniauth_path_prefix = "/my_engine/u/auth" end。如果这对你有用,我会更新我的答案。 我仍然得到相同的Not found. Authentication passthru. 错误。您是否覆盖了OmniauthCallbacksController#passthru?因为我没有 嗨@TerencePonce,你最后解决了吗?我真的很感兴趣。【参考方案2】:

我找到了更好的解决方案。更新你的 lib/MyEngine/engine.rb。 使用此解决方案,您不必添加设计范围部分(我的示例仅适用于 facebook)

module MyEngine
  require 'omniauth'
  require 'omniauth-facebook'

  class Engine < ::Rails::Engine
    isolate_namespace SimpleUser

    middleware.use OmniAuth::Builder do
      provider :facebook, ENV['FACEBOOK_KEY'], ENV['FACEBOOK_SECRET'], :scope => ENV['FACEBOOK_SCOPE']
  end
end

【讨论】:

这不会在routes.rb 中为我生成任何不更改的引擎路线

以上是关于“未找到。身份验证通道。”错误。设计 Omniauthable 模块在另一个引擎中时不起作用的主要内容,如果未能解决你的问题,请参考以下文章

前端错误监控的简单设计与实现

前端错误监控的简单设计与实现

软件设计要素初探:软件设计的一些子主题

1.10程序设计错误

错误码设计

设计老鸟也会犯的3个响应式设计错误