Deviseomniauthable 因“无法找到有效的路径映射”而破坏了 Omniauth 身份验证
在我的项目中,我有两种类型的用户:求职者和招聘经理。求职者没有模型,他们只能使用从第三方提供商收到的数据来申请工作,同时通过 Omniauth 进行身份验证。招聘经理的信息存储在设计用户模型中。招聘经理还必须能够使用其公司的 Google 电子邮件帐户登录。 因此,首先我使用 Omniauth 1.0.0、Rails 3.1.3 构建了求职者的身份验证:
omniauth.rb
require 'omniauth-openid'
require 'openid/store/filesystem'
Rails.application.config.middleware.use OmniAuth::Builder do
provider :openid, :store => OpenID::Store::Filesystem.new('./tmp'), :name => 'google', :identifier => 'https://www.google.com/accounts/o8/id'
provider :facebook, "xxxxxxxxx", "xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
{:scope => 'email, offline_access, publish_stream', :client_options => {:ssl => {:ca_file => '/usr/lib/ssl/certs/ca-certificates.crt'}}}
provider :twitter, "xxxxxxxxxxx", "xxxxxxxxxxxxxxxxxxxxxxxxxxx"
provider :linkedin, "xxxxxxxxxxx", "xxxxxxxxxxxxxxxxxxx"
end
in routes.rb
:
match '/auth/:provider/callback', :to => 'sessions#authenticate_jobseeker'
match '/auth/failure', :to => 'sessions#failure'
in sessions_controller.rb< /code>
def authenticate_jobseeker
session[:jobseeker] = request.env['omniauth.auth']
if valid_job_seeker?
redirect_to new_job_application_path(...)
else
redirect_to request.env['omniauth.origin'] || root_path, alert: "Authentication failure"
end
end
到目前为止,一切正常。然而,当我开始为用户模型实现 Google 登录并添加 :omniauthable 时,我的求职者身份验证失败了。我正在使用 Devise 1.5.2:
user.rb
class User < ActiveRecord::Base
#...
devise :database_authenticatable, :registerable,
... :lockable, :omniauthable
#...
end
in devise.rb
:
config.omniauth :open_id, :store => OpenID::Store::Filesystem.new('./tmp'), :name => 'google', :identifier => 'https://www.google.com/accounts/o8/id', :require => 'omniauth-openid'
in routes.rb
:
devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" } do
get '/users/auth/:provider' => 'users/omniauth_callbacks#passthru'
end
此时,用户身份验证有效,但求职者却没有。搜索了一段时间后,通过添加 :path_prefix => 解决了这个问题。 “/auth”
到 omniauth.rb
中的每个提供者。 现在唯一的问题是,当求职者不允许访问其数据时(即按“不允许”并返回到应用程序),我会为每个提供商提供以下运行时错误:
Could not find a valid mapping for path "/auth/twitter/callback"
Parameters:
{"denied"=>"mKjVfMRwRAN12ZxQ9cxCoD4rYSLJIRLnEqgiI"}
跟踪顶部:
devise (1.5.2) lib/devise/mapping.rb:48:in `find_by_path!'
devise (1.5.2) lib/devise/omniauth.rb:17:in `block in <top (required)>'
omniauth (1.0.0) lib/omniauth/strategy.rb:418:in `call'
omniauth (1.0.0) lib/omniauth/strategy.rb:418:in `fail!'
omniauth-oauth (1.0.0) lib/omniauth/strategies/oauth.rb:63:in `rescue in callback_phase'
omniauth-oauth (1.0.0) lib/omniauth/strategies/oauth.rb:45:in `callback_phase'
omniauth (1.0.0) lib/omniauth/strategy.rb:200:in `callback_call'
omniauth (1.0.0) lib/omniauth/strategy.rb:166:in `call!'
omniauth (1.0.0) lib/omniauth/strategy.rb:148:in `call'
omniauth (1.0.0) lib/omniauth/strategy.rb:168:in `call!'
omniauth (1.0.0) lib/omniauth/strategy.rb:148:in `call'
omniauth (1.0.0) lib/omniauth/strategy.rb:168:in `call!'
omniauth (1.0.0) lib/omniauth/strategy.rb:148:in `call'
omniauth (1.0.0) lib/omniauth/builder.rb:30:in `call'
我一直在现在正在尝试解决它一段时间。非常感谢任何帮助。如果我可以提供更多信息,请告诉我。
In my project, I have two type of users: job seekers and hiring managers. Job seekers don't have a model, they are just able to apply for jobs using the data received from from third-party providers while authenticating thru Omniauth. Hiring managers' info is stored in devise User model. Hiring managers also must be able to sign in with their company's Google email account.
So, first I built job seekers' authentication using Omniauth 1.0.0, Rails 3.1.3:
omniauth.rb
require 'omniauth-openid'
require 'openid/store/filesystem'
Rails.application.config.middleware.use OmniAuth::Builder do
provider :openid, :store => OpenID::Store::Filesystem.new('./tmp'), :name => 'google', :identifier => 'https://www.google.com/accounts/o8/id'
provider :facebook, "xxxxxxxxx", "xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
{:scope => 'email, offline_access, publish_stream', :client_options => {:ssl => {:ca_file => '/usr/lib/ssl/certs/ca-certificates.crt'}}}
provider :twitter, "xxxxxxxxxxx", "xxxxxxxxxxxxxxxxxxxxxxxxxxx"
provider :linkedin, "xxxxxxxxxxx", "xxxxxxxxxxxxxxxxxxx"
end
in routes.rb
:
match '/auth/:provider/callback', :to => 'sessions#authenticate_jobseeker'
match '/auth/failure', :to => 'sessions#failure'
in sessions_controller.rb
def authenticate_jobseeker
session[:jobseeker] = request.env['omniauth.auth']
if valid_job_seeker?
redirect_to new_job_application_path(...)
else
redirect_to request.env['omniauth.origin'] || root_path, alert: "Authentication failure"
end
end
Up to this point everything worked fine. However, when I started implementing Google sign on for User model, and added :omniauthable to it, my job seeker authentication broke. I am using Devise 1.5.2:
user.rb
class User < ActiveRecord::Base
#...
devise :database_authenticatable, :registerable,
... :lockable, :omniauthable
#...
end
in devise.rb
:
config.omniauth :open_id, :store => OpenID::Store::Filesystem.new('./tmp'), :name => 'google', :identifier => 'https://www.google.com/accounts/o8/id', :require => 'omniauth-openid'
in routes.rb
:
devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" } do
get '/users/auth/:provider' => 'users/omniauth_callbacks#passthru'
end
At this point, Users' authentication worked, but job seekers' did not. After searching for a while, the issue was fixed by adding :path_prefix => "/auth"
to every provider in omniauth.rb
.
The only problem now, is when job seeker does not allow access to its data (i.e. presses "Don't Allow" and comes back to the application), I get following RuntimeError for every provider:
Could not find a valid mapping for path "/auth/twitter/callback"
Parameters:
{"denied"=>"mKjVfMRwRAN12ZxQ9cxCoD4rYSLJIRLnEqgiI"}
top of the trace:
devise (1.5.2) lib/devise/mapping.rb:48:in `find_by_path!'
devise (1.5.2) lib/devise/omniauth.rb:17:in `block in <top (required)>'
omniauth (1.0.0) lib/omniauth/strategy.rb:418:in `call'
omniauth (1.0.0) lib/omniauth/strategy.rb:418:in `fail!'
omniauth-oauth (1.0.0) lib/omniauth/strategies/oauth.rb:63:in `rescue in callback_phase'
omniauth-oauth (1.0.0) lib/omniauth/strategies/oauth.rb:45:in `callback_phase'
omniauth (1.0.0) lib/omniauth/strategy.rb:200:in `callback_call'
omniauth (1.0.0) lib/omniauth/strategy.rb:166:in `call!'
omniauth (1.0.0) lib/omniauth/strategy.rb:148:in `call'
omniauth (1.0.0) lib/omniauth/strategy.rb:168:in `call!'
omniauth (1.0.0) lib/omniauth/strategy.rb:148:in `call'
omniauth (1.0.0) lib/omniauth/strategy.rb:168:in `call!'
omniauth (1.0.0) lib/omniauth/strategy.rb:148:in `call'
omniauth (1.0.0) lib/omniauth/builder.rb:30:in `call'
I've been trying to solve it for a while now. Any help is greatly appreciated. Let me know, if I can provide additional info.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

发布评论
评论(2)
您是否在模型中的某处使用omniauth[“user_info”]?就我而言,我正在访问
omniauth["user_info"]["email"]
,这会崩溃,我会得到同样的错误,被设备捕获。
在我的应用程序中,我们直接使用omniauth(对于企业)以及使用device+facebook 进行用户登录。
不过,还没有弄清楚如何避免失败。 Devise 注册了自己的失败应用程序。当我弄清楚时会更新。
更新:很抱歉,我似乎误读了您问题的部分内容。您可以看到远程 Web 应用程序授权明显失败,这似乎是堵塞的,而不是代码中的屏蔽异常(就像我的情况一样)。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
回答我自己的问题。因此,最终决定采用纯粹的 Omniauth 实施。我从
User
模型中删除了:omniauthable
,从devise.rb
中删除了config.omniauth...
,删除了 < code>:omniauth_callbacks 从routes.rb
设计路由。,所有用户(无论什么角色)都将使用相同的回调路由并点击
sessions_controller#authenticate_jobseeker
操作(应该考虑重命名该操作?):和
User.find_from_oauth
:因此 实施满足了所有要求。
Answering my own question. So, final decision was to go with pure Omniauth implementation. I removed
:omniauthable
fromUser
model, removedconfig.omniauth...
fromdevise.rb
, removed:omniauth_callbacks
devise routes fromroutes.rb
.So, all users (no matter what role) would use ame callback routes and hit
sessions_controller#authenticate_jobseeker
action (should consider renaming the action?):and
User.find_from_oauth
:This implementation satisfied all of the requirements.