好的 我们有一个运行良好的应用程序。几周前,一位(现在是前)员工做出了相当大的改变,这似乎导致了一个相当奇怪的错误,我试图找出实际的问题是什么,当然也解决它。
简而言之,这是一个失败的场景:
在应用程序中,我们使用 devise(我相信是 4.6.2)来验证用户身份,使用 CanCanCan 来授权资源,并使用 Ahoy 来跟踪某些类型的用户(在本例中为管理员)。
对于我们遇到的失败,我们有两条相关的路线:
/users/sign_in
<- This is a devise routeGET /user
<- This is a route which returns some relevant information regarding the current user including the user role and a JWT 令牌,他们可以使用它来执行 API 调用GET /user
端点在控制器内部定义:UsersController < V2::ApplicationController
,应用程序控制器中有一些钩子,相关的是:before_action :authenticate_user!, :update_current_session
,其中update_current_session
看起来像这样:
def current_session
return unless current_user
@current_session ||= current_user.sessions.find_by_session_id(cookies.signed[:_session_id])
end
def update_current_session
return unless current_session
current_session.accessed!(request)
end
所以据我了解,
authenticate_user!
使用devise,然后调用update_current_session函数。
我们有一些内部测试/脚本需要
/user
返回的令牌,因为它们对我们的应用程序执行 API 调用。因此他们做了以下事情:
/users/sign_in
执行 POST 调用
{
"user": {
"email": "[email protected]",
"password": "whatever"
}
}
success: "true"
。
Set-Cookie
标头:
Set-Cookie: ahoy_visit=[REDACTED]; path=/; expires=Mon, 20 Apr 2020 13:34:21 GMT; HttpOnly
Set-Cookie: _session_id=[REDACTED]; path=/; expires=Mon, 20 Apr 2020 10:34:21 GMT; HttpOnly
Set-Cookie: st_session=[REDACTED]; path=/; expires=Wed, 20 May 2020 09:34:21 GMT; HttpOnly
Set-Cookie: _safe_cookies__known_cookies=ahoy_visitor%7Cahoy_visit%7C_session_id%7Cst_session; path=/; expires=Thu, 18 Apr 2030 09:34:21 GMT; HttpOnly
/user
调用 GET
Cookie
,这只是所有这些 Set-Cookie 参数在一起(或者只是多个
Cookie
标头,两者都有效
在第一次调用 POST
/users/sign_in
时,st_session cookie 似乎比以前更短。 如果我们连续调用 POST
/users/sign_in
两次,则流程有效:
st_session
好像是因为
session_store.rb
里面的配置:
Rails.application.config.session_store :cookie_store, key: 'st_session', expire_after: (Rails.env.production? ? 1.hour : 1.month), secure: Rails.env.production?
总结
devise.rb
和我们的
sessions_controller
,但 401 故障似乎发生在这些地方之外。有人知道什么可能导致这个问题吗?我试图调试并找出问题所在,但似乎无法取得相关进展。这似乎与 Devise/Warden 有关,但我不太熟悉那里发生的事情。
我更想知道谁存储了
st_session
cookie 以及what 存储在其中,因为看起来第一次丢失某些东西(因为 st_session)更短,而且看起来 devise 无法正确根据该值对用户进行身份验证。 感谢任何帮助,甚至指导我到代码中的相关位置,我可以寻找答案/帮助调试
谢谢你。
:timeoutable
current_user
中有任何
ApplicationController
调用,它们将触发身份验证过程。由于会话超时,在到达会话控制器中的登录代码之前会触发 401 错误。
我的解决方案是将以下行添加到会话控制器:
prepend_before_action :reset_session, only: [:create]