我们的产品是一个 Rails 应用程序;身份验证由 Devise 和 OmniAuth 处理。总共约 2000 个用户。我们最近收到了一些用户无法登录的报告,但我们无法弄清楚原因。在我们的生产日志中没有收到任何服务器错误或任何内容来暗示任何事情都是错误的。
让我们看一些代码……</p>
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
...
def twitter
oauthorize "twitter"
end
private
def oauthorize(provider)
if env['omniauth.auth']
@identity = Identity.from_omniauth(env['omniauth.auth'])
@person = @identity.person
# 1. failing here? Maybe?
if @person
PersonMeta.create_for_person(@person, session[:referrer], session[:landing_page]) if @person.first_visit?
# 2. PersonMetas *aren't* being created.
flash[:notice] = I18n.t("devise.omniauth_callbacks.success", kind: provider)
sign_in_and_redirect(@person, :event => :authentication)
# 3. Definitely failing by here…
else
redirect_to root_url
end
else
redirect_to root_url
end
end
end
class Identity < ActiveRecord::Base
belongs_to :person, counter_cache: true, touch: true
after_create :check_person
def self.from_omniauth(auth)
where(auth.slice("provider", "uid")).first_or_initialize.tap do |identity|
identity.oauth_token = auth['credentials']['token']
identity.oauth_secret = auth['credentials']['secret']
case auth['provider']
when "twitter"
identity.name = auth['info']['name']
identity.nickname = auth['info']['nickname']
identity.bio = auth['info']['description']
identity.avatar_address = auth['info']['image']
else
raise "Provider #{provider} not handled"
end
identity.save
end
end
def check_person
if person_id.nil?
p = create_person(nickname: nickname, name: name, remote_avatar_url: biggest_avatar)
p.identities << self
end
end
def biggest_avatar
avatar_address.gsub('_bigger', '').gsub('_normal', '') if avatar_address
end
end
class PersonMeta < ActiveRecord::Base
attr_accessible :landing_page, :mixpanel_id, :referrer_url, :person_id
belongs_to :person
def self.create_for_person(person, referrer, landing_page)
PersonMeta.create!(referrer_url: referrer, landing_page: landing_page, person_id: person.id)
end
end
所以我们有了它,而且我们在生产中没有遇到任何错误。
我们从哪里开始?好吧,让我们看看失败点是不是Identity.from_omniauth
此方法搜索现有身份(我们为更多提供者编写了额外的代码,但尚未在客户端实现)。如果没有找到身份,它将创建一个,然后创建关联的 Person 模型。如果这是故障点,我们将能够在生产控制台中看到一些可疑的空字段。但是没有——Person & Identity 模型已经创建了所有正确的字段,并且应用程序的相关部分已经看到了它们(例如,它们的“用户个人资料页面”都已创建)。
我刚刚添加if @person
到#oauthorize - 我们有一个 500 where @identity.person
was nil
,但无法复制。
无论如何,有问题的现实世界用户确实拥有完整的模型和完整的关联。向下移动方法,然后我们创建一个PersonMeta
记录来记录简单的东西,比如登陆页面。我会这样做after_create
,Person
但我认为将会话数据传递给模型是不正确的。
这不是为我们有问题的用户创建的。在这一点上,我有点难过。我不确定如何创建!(砰的一声)进去了,但是如果东西坏了,这不应该抛出异常吗?它不是。
无论如何,只有当这是一个人的第一次访问时才会调用它 - 后续登录应该绕过它。有问题的用户之一是我的朋友,所以我一直在让他尝试各种其他事情,包括再次登录、尝试不同的浏览器等,而且这种情况一直在发生
所以无论如何,在花了 45 分钟写这篇文章之后……</h1>
其中一名用户通过 Twitter 撤销了对该应用程序的访问权限并重新进行了身份验证。现在一切正常。
我勒个去?
他的旧身份正确存储了他的 OAuth 令牌等。
幸运的是,这已为一位用户解决,但这显然是一个持续存在的问题。
我们做什么?