首页 > 解决方案 > Rails /设计注销,登录和过期之间的间歇性会话问题

问题描述

我正在准备我的第一个 Rails 在线部署,我非常接近一个有限的、封闭的版本,供用户试用。

我的问题是,如何强制并保证在适当的时间从浏览器中清除本地用户会话数据?

我遇到的问题是当有人在一段空闲时间后(即会话超时后)登录或注册时引发间歇性(看起来像永久性和致命的应用程序故障,但事实并非如此)错误:“我们很抱歉,但是出了点问题。” 其他设备上的另一个用户不会收到此错误。该应用程序登录并按预期为他们运行。

日志显示(删除了多余的信息):

Started GET "/" for xxx.xxx.xxx.xxx at 2021-06-27 13:37:25 +1000
D, SELECT  "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."first_name" ASC LIMIT $2  [["id", "b2186826-a1f7-48ca-9d04-825b3d8b3e4c"], ["LIMIT", 1]]   
F, ActiveRecord::StatementInvalid (PG::UndefinedObject: ERROR:  unrecognized configuration parameter "session.tenant_id"
: SELECT  "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."first_name" ASC LIMIT $2):
F, activerecord (5.2.6) lib/active_record/connection_adapters/postgresql_adapter.rb:622:in `exec_prepared'
activerecord (5.2.6) lib/active_record/connection_adapters/postgresql_adapter.rb:622:in `block (2 levels) in exec_cache'
activesupport (5.2.6) lib/active_support/dependencies/interlock.rb:48:in `block in permit_concurrent_loads'
.
.
.

该应用程序是多租户的,并使用两个 Postgres 会话变量 - 一个用于用户访问级别(要应用的 Postgres RLS 角色:登录名、租户或应用程序管理员),另一个用于租户 ID(这是 session:tenant_id 错误的来源,以上)。每次调用控制器操作时都会相应地设置这些,以保持与数据库中 RLS 的完整性。

我还设计了可超时设置为 60 分钟,并在以下链接中使用该方法在此延迟之后将人们踢出并返回登录(我还不相信指定的延迟正在兑现,但这是另一个故事) -链接:https ://medium.com/code/user-session-inactivity-timeout-with-rails-and-devise-7269ac3a8213

在应用服务器上,再多的 puma 重启或服务器重启都不会恢复服务器。该错误仅显示在最近超时的特定设备上(有时也用于注销)。如果另一个用户从另一个设备登录,他们不会遇到故障,并且服务器会按预期工作。如果我清除了故障设备上的浏览器缓存和 cookie,它将恢复为它们运行。

根据我的阅读,Devise 会在登录和注销时自动重置浏览器上的会话???本地会话数据只是搜索参数。我对几个列表视图进行了基本搜索......也许如果我改为使用 Datatables,我可以取消存储会话数据......也许这可以避免我遇到的问题?

其次,由于这种间歇性行为,我正在考虑试用令牌身份验证。请参阅https://www.pluralsight.com/guides/token-based-authentication-with-ruby-on-rails-5-api。想法?

标签: ruby-on-railssessiondevise

解决方案


我已经解决了这个问题......我现在也可以看到实际上发生了什么......

似乎用于行级别安全性的 postgres 参数/变量在大约五分钟没有活动的标记处丢失,导致崩溃错误消息。这一定是由于设计了在大约 5 分钟不活动后将用户注销的结果(根本没有为此配置!)

修复方法是将以下内容放入 database.yml 文件中,在默认部分的主机和端口设置下:

  variables:
    session.access_level: "guest"
    session.tenant_id: ""

现在我得到的是优雅的注销并返回登录表单。这里的问题是设计超时设置是什么并不重要——无论是被删除(从用户模型和设计初始化程序中)还是设置为 60 分钟,这都没有影响......无论用户在做什么,不活动大约 5 分钟会导致他们被注销。我宁愿把它延长到大约 60 分钟。


推荐阅读