如何在rails应用程序中设置如果任何用户空闲30分钟或特定时间段,他应该自动退出。 可以任何人给出任何解决方案。我正在使用设计进行身份验证。任何帮助表示赞赏。
答案 0 :(得分:24)
您应该使用Timeoutable
模特特征。
Timeoutable负责确定用户会话是否已经过期。当会话在配置的时间后到期时,将再次要求用户提供凭据,这意味着,他/她将被重定向到登录页面。
选项
Timeoutable将以下选项添加到devise_for:
- + timeout_in +:没有活动的用户会话超时的时间间隔。
在您的模型中,您需要
devise :timeoutable
# along with :database_authenticatable, :registerable and other things.
另外,看一下config/initializers/devise.rb
,你可以在那里配置超时值。
答案 1 :(得分:11)
我知道这个问题已经得到了解答,但我认为我也会提供我的解决方案,因为在我的情况下,我正在寻找比Devise的超时功能所能提供的功能更多的功能。非常感谢@Sergio Tulentsev在他的回答的评论部分为我提供了有用的解释和想法!
因为Devise在服务器端而不是客户端运行,所以当身份验证令牌超时时,客户端在用户执行调用Rails控制器的操作之前不会知道超时。这意味着在执行调用Rails控制器的操作之前,用户不会在超时时重定向到登录页面。
在我的情况下,这是一个问题,因为我的网页包含用户敏感信息,如果用户忘记注销并且页面上没有执行任何操作,我不想无限期地显示这些信息。
我安装了gem auto-session-timeout,它将代码添加到客户端,以定期检查身份验证令牌是否已过期。
它在自述文件中没有说,但自动会话超时需要jquery-periodicalupdater才能工作。 This page包含以下原因:
以下是为了让自动会话超时与Devise一起使用而采取的步骤:
首先,我按照步骤here来自定义Devise会话控制器。仅供参考,我的 config / routes.rb 文件按以下方式设置:
Myapp::Application.routes.draw do
devise_for :users, controllers: { sessions: "users/sessions" }
#other routes
end
在 app / controllers / users / sessions_controller.rb 中,我有以下代码:
class Users::SessionsController < Devise::SessionsController
layout 'login' #specifies that the template app/views/layouts/login.html.erb should be used instead of app/views/layouts/application.html.erb for the login page
#configure auto_session_timeout
def active
render_session_status
end
def timeout
flash[:notice] = "Your session has timed out."
redirect_to "/users/sign_in"
end
end
在 app / controllers / application_controller.rb 中,我有以下代码:
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
before_action :authenticate_user!
auto_session_timeout 30.minutes
end
请注意,我们使用auto_session_timeout将身份验证令牌到期时间设置为30分钟。这取代了Devise超时功能。
在我的应用中,我有两个布局模板 - 一个用于用户登录时看到的所有页面( app / views / layouts / application.html.erb ),一个仅用于登录屏幕( app / views / layouts / login.html.erb )。在这两个文件中,我在html <body>
元素中添加了以下行:
<%= auto_session_timeout_js %>
此代码将生成Javascript,每隔60秒检查一次身份验证令牌的状态(此时间间隔是可配置的)。如果令牌已超时,则Javascript代码将调用 app / controllers / users / sessions_controller.rb 文件中的timeout
方法。
请注意,我已将此代码包含在 app / views / layouts / login.html.erb 页面中。这是因为如果登录页面上没有活动超过30分钟(或 application_controller.rb 文件中的auto_session_timeout
设置),则认证令牌将过期,用户在尝试登录时将收到无效的身份验证令牌错误。添加代码<%= auto_session_timeout_js %>
将导致在身份验证令牌过期时刷新登录,从而防止发生此错误。
答案 2 :(得分:5)
使用Devise Gem:
我们可以使用设计宝石的内置功能,但在超时后它不会自动重定向到登录页面,重定向将在我们执行任何操作后完成。
我们可以执行自动退出:
使用gem“auto-session-timeout”
https://github.com/pelargir/auto-session-timeout
使用此gem的缺点是,如果用户只键入(执行按键事件)直到超时时间,它将自动注销。
我们可以通过使用Javascript来覆盖劣势:
第1步:定义路线
get 'application/session_time'
第2步:JavaScript将包含
$(document).ready(function(){
if($("#user_logged").is(":visible") == true )
{
$(document).on( "keypress keydown", function () {
console.log("hello");
$.ajax({
type:"GET",
url:"/application/session_time",
dataType:"html",
});
});
}
});
第3步:应用程序控制器将包含:
@session_time = 5.minute
auto_session_timeout @session_time
def session_time
@session_time = 5.minute
end
第4步:div找到它是否登录页面
<% if user_signed_in? %>
<div id="user_logged"></div>
<% end %>
保留空白div是因为我们必须仅在用户登录时加载JavaScript,因此不是查找当前用户是否为零。
我已经完成了空白div,如果用户登录它将可用,因此在JavaScript开始时检查是否存在div_id“user_loged”。
答案 3 :(得分:0)
有一种没有提及的简单方法,不需要额外的宝石或依赖项。
在initializers/devise.rb
中说,您已设置config.timeout_in = 30.minutes
并将:timeoutable
添加到模型中。当用户登录时,触发页面加载以下JavaScript:
setAccurateTimeout(() => {
window.location.reload();
}, 30 * 60 * 1000); // minutes (from devise setting) * sec * ms
function setAccurateTimeout(callback, length) {
// adjust any discrepencies every 5s
let speed = 5000,
steps = length / speed,
count = 0,
start = new Date().getTime();
function instance() {
if (count++ == steps) {
callback();
} else {
// console.log(`step ${count} of ${steps}, time passed ${count * speed}ms of ${length}ms`)
let diff = (new Date().getTime() - start) - (count * speed);
// console.log(`accuracy diff ${diff}ms, adjusted interval: ${speed - diff}ms`);
window.setTimeout(instance, (speed - diff));
}
}
window.setTimeout(instance, speed);
}
常规setTimeout
可能会被使用,尽管随着时间的推移,它会由于CPU使用率而带来不准确的情况。可能会导致退出登机的时间比预期的稍晚。
由于在客户端javascript之前进行了初始化,因此服务器将在会话结束之前稍稍终止会话。页面重新加载时,浏览器将最终显示在登录屏幕上。这种方法还可以很容易地预先触发警告模式,例如在2分钟标记处,倒数显示剩余的秒数,并可以单击按钮以保持登录状态。
额外提示:在“保持登录状态”按钮上,将网址设置为您的网页之一,并添加data-remote='true'
属性。单击此按钮将向服务器发出请求,而无需重新加载用户所在的页面,从而满足活动要求并重置设备的超时,而无需重新加载或导航到任何地方。取消所有程序化页面重新加载,然后重新启动主超时。