什么是Catalyst应用程序的最佳动作持久性技术?

时间:2009-01-06 22:12:34

标签: perl catalyst

我正在编写一个Catalyst应用程序,它需要有一个相当短的会话到期时间(15分钟)。我正在使用标准的Catalyst框架身份验证模块,因此用户数据存储在会话中 - 即,当会话到期时,您将被注销。

此应用程序的许多用途需要> 15分钟才能完成,因此用户经常会提交表单,但却发现他们的会话状态已经消失,他们需要重新登录。

如果发生这种情况,我希望保留原始表单提交,如果他们成功登录,请继续并执行表单提交,就像会话未过期一样。

我已经通过控制器中的auto()方法处理了身份验证内容 - 如果您请求需要身份验证的操作并且您当前未登录,则会重定向到login()方法,它显示登录表单,然后在提交后处理它。似乎应该可以在auto方法重定向到login()时存储请求和任何表单参数,然后在login()成功时将它们拉回来 - 但我不完全确定最好的以通用/标准/可重用方式获取或存储此信息的方法。 (我正在考虑将它存储在会话中,然后在它被撤回后将其删除;如果这看起来是个坏主意,那还有其他问题需要解决。)

是否有标准的“最佳做法”或食谱方式来做到这一点?

(一个皱纹:这些表格是通过POST提交的。)

5 个答案:

答案 0 :(得分:4)

我不禁想到,在一个应用程序中强制执行15分钟超时是一个根本性的缺陷,通常需要在15分钟之间执行操作。

尽管如此,我会考虑覆盖Catalyst::Plugin::Session->delete_session方法,以便$c->request->body_parameters的任何内容被序列化并保存(可能是数据库)以供以后恢复。您可能希望对POST参数进行一些初步检查,以确保它们符合您的期望。

同样,create_session需要负责将这些数据从数据库中拉回来并使其可用于原始表单操作。

看起来确实像一个混乱的局面,我倾向于重复我的第一句......

更新:

无论您使用delete_session还是auto,矛盾的问题仍然存在:您无法在会话中存储此信息,因为超时事件会破坏会话。你必须将它存储在一个更永久的地方,以便在会话重新初始化后幸存下来。 Catalyst::Plugin::Session本身正在使用Storable,您应该可以使用以下内容:

use Storable;
...
sub auto {
    ...
    unless (...) { #ie don't do this if processing the login action
        my $formitems = freeze $c->request->body_parameters;
        my $freezer = $rs->update_or_create(
              {user => $c->user, formitems => $formitems} );
        # Don't quote me on the exact syntax, I don't use DBIx::Class
    }
    ...
    my $formitems = $c->request->body_parameters
                  || thaw $rs->find({$user => $c->user})->formitems
                  || {} ;
    # use formitems instead of $c->request->body_parameters from here on in

基础表可能有(用户CHAR(x),formitems TEXT)或类似的。也许是一个时间戳,以便没有任何过时的东西得到恢复。您可能还希望存储正在处理的操作,以确保检索到的表单项属于正确的表单。您比我更了解您的应用程序的问题。

答案 1 :(得分:2)

我会将表单数据存储为模型中的某种用户数据。

Catalyst::Plugin::Session::PerUser是这样做的一种方式(虽然有点骇人听闻)。我建议仅使用会话插件进行身份验证,并将所有状态信息存储在存储用户数据的模型中。

我完全同意RET的观点,即15分钟的限制在这种情况下似乎反效果。

答案 2 :(得分:1)

我在搜索CPAN时遇到了完全不相关的事情。

Catalyst::Plugin::Wizard声称可以完全满足您的需求。文档建议它可以重定向到登录页面,同时保留上一个操作的状态。

注意:我没有使用它,所以不能保证它的有效性。

答案 3 :(得分:1)

最后,我们最终在auto()中抓取待处理请求(URL + params),对其进行序列化和加密,并通过登录页面上的隐藏表单元素传递它。如果我们获得了填充了隐藏元素的登录请求,我们会对其进行解密和反序列化,然后进行适当的重定向(确保通过标准“此用户可以执行此操作”代码路径)。

答案 4 :(得分:0)

您可以在客户端上始终使用一些javascript,通过每隔几分钟发出一个小请求来阻止会话过期。

或者,您可以在发布表单之前让AJAX检查活动会话,并在需要时向用户显示新的登录框。