2011-05-02 156 views
45

这似乎很简单:我试图让我的轨活动记录会话超时2分钟后。所以两分钟后,我希望我的用户不得不重新登录。在Rails 3中设置会话超时

我刚刚在本地开发机器上运行rails server(即WebBrick)。

我知道这是什么做的config/initalizers/session_store.rb下面的代码,但我不认为我有相当钉它:

CodedOn::Application.config.session_store :active_record_store 

CodedOn::Application.configure do 
    config.action_controller.session = {:expire_after => 2.minutes} 
end 

这似乎并不工作,或者至少我的会议似乎没有超时。我无法找到很多关于Rails 3的方法来做到这一点,因为我知道事情已经从Rails 2.x中改变了。

有人可以帮我吗?

回答

46

我想你将不得不手动这样做,因为活动记录存储没有实现expire_after选项。因此,内过滤器,然后(我认为),你应该这样做:

def authenticate 
    if session[:logged_in] 
    reset_session if session[:last_seen] < 2.minutes.ago 
    session[:last_seen] = Time.now 
    else 
    ... authenticate 
    session[:last_seen] = Time.now 
    end 
end 

显然,这是不完整的,但它应该给你的基本理念。

UPDATE

看来这个功能,因为2.3版本目前在轨。我找到了相关的代码here。这是AbstractStore,它应该用作所有派生类的基类。因此,正如dadooda所建议的那样,以下内容应该可以工作:

Some::Application.config.session_store :active_record_store, { 
    expire_after: 24.hours, 
} 
+0

难怪我无法找到它:)感谢您的指针。 – 2011-05-02 20:56:23

+1

这里的一个问题是,这个工作是如何进行的,例如当会话初始创建时调用'before_filter',也就是说,当用户首次通过身份验证时,'session [:last_seen]'如何再次被调用?如果它是一个authenticate before_filter,是不是只调用一次 - 在身份验证?我想我脑海里想的是,一旦创建了会话并且用户登录了,我该如何检查'session [:last_seen]',以便如果它超过了X分钟的数量,迫使他们重新登录,而不是在最初创建会话时进行重新登录。希望这是有道理的 – marcamillion 2011-10-10 08:11:33

+1

我希望我得到你的问题:HTTP是无状态的。因此,网络服务器在任何两个请求之间都没有看到任何关系。但有些用例要求这种关系(例如认证)。在rails中,会话散列提供了这一点。但是控制器必须为每个请求读取会话散列,以便识别先前认证的用户。因此,在每次请求之前调用过滤器之前的'authenticate'。我希望这有帮助。 – moritz 2011-10-10 20:05:39

4

您必须手动完成。以下是为ActiveRecord会话创建类方法的示例。你可以使用Rufus-Scheduler和/或DelayedJob定期调用它。为什么这很重要

class Session < ActiveRecord::Base 
    def self.sweep(time = 1.hour) 
    if time.is_a?(String) 
     time = time.split.inject { |count, unit| count.to_i.send(unit) } 
    end 

    delete_all "updated_at < '#{time.ago.to_s(:db)}' OR created_at < '#{2.days.ago.to_s(:db)}'" 
    end 
end 

更多的背景:http://guides.rubyonrails.org/security.html#session-expiry

2

到期时间。

MAX_SESSION_TIME = 60 * 60 

before_filter :prepare_session 

def prepare_session 

    if !session[:expiry_time].nil? and session[:expiry_time] < Time.now 
     # Session has expired. Clear the current session. 
     reset_session 
    end 

    # Assign a new expiry time, whether the session has expired or not. 
    session[:expiry_time] = MAX_SESSION_TIME.seconds.from_now 
    return true 
end 
35

我这样做的简单的方法,你可以试试这个:

在你config/initializers/session_store.rb只是这样做:

Yourapp::Application.config.session_store :cookie_store, 
              :key => "_yourapp_session", 
              :expire_after => 2.minutes 

这是为我工作细致,希望对你的作品也。

+2

这很完美,谢谢! – sowasred2012 2013-06-06 09:35:19

+1

这也适用于Rails 4。 – 2014-07-27 17:57:12

+0

@ sowasred2012非常欢迎 – Ravindra 2014-07-30 10:09:34

4

mosch说:

我认为你必须手动做到这一点,因为活动记录存储不落实expire_after选项。

看来它不再是这种方式。对应用的每个请求后

Some::Application.config.session_store :active_record_store, { 
    key: "some_session_id", 
    domain: ".isp.com", 
    expire_after: 24.hours, 
} 

该Cookie自动延长::expire_after对Rails 3.2.11为我工作。会话通过浏览器退出持续存在。

为了简单的SSO功能,我做了上面的技巧来跨域“全局化”会话,似乎到目前为止工作。

-4

只需添加timeout_in方法在你的模型,它应该做的伎俩:

 
    def timeout_in 
    2.minutes 
    end