Catalyst 应用程序的最佳操作持久性技术是什么?
我正在编写一个 Catalyst 应用程序,该应用程序需要相当短的会话过期时间(15 分钟)。 我正在使用标准的 Catalyst 框架身份验证模块,因此用户数据存储在会话中 - 即,当您的会话过期时,您将被注销。
此应用程序的许多使用都需要超过 15 分钟才能完成,因此用户经常会提交表单,却发现他们的会话状态消失了,并且需要重新登录。
如果发生这种情况,我想保留原始状态表单提交,如果登录成功,则继续进行表单提交,就像会话未过期一样。
我已经通过控制器中的 auto() 方法处理身份验证内容 - 如果您请求需要身份验证的操作并且当前未登录,您将被重定向到 login() 方法,该方法显示登录表单,然后在提交后对其进行处理。 当 auto 方法重定向到 login() 时,似乎应该可以存储请求和任何表单参数,然后在 login() 成功时将它们拉出来 - 但我不完全确定最好的方法以通用/标准/可重用的方式获取或存储此信息的方法。 (我正在考虑将其存储在会话中,然后在将其拉出后将其删除;如果这看起来是一个坏主意,那就需要解决其他问题。)
是否有标准的“最佳实践”或食谱方法可以做到这一点?
(一个问题:这些表格是通过 POST 提交的。)
I'm writing a Catalyst application that's required to have a fairly short session expiration (15 minutes). I'm using the standard Catalyst framework authentication modules, so the user data is stored in the session -- i.e., when your session expires, you get logged out.
Many of the uses of this application will require >15 minutes to complete, so users will frequently submit a form only to find their session state is gone and they're required to log back in.
If this happens I want to preserve the original form submission, and if they log in successfully, continue on and carry out the form submission just as if the session had not expired.
I've got the authentication stuff being handled by an auto() method in the controller -- if you request an action that requires authentication and you're not currently logged in, you get redirected to the login() method, which displays the login form and then processes it once it's submitted. It seems like it should be possible to store the request and any form parameters when the auto method redirects to the login(), and then pull them back out if the login() succeeds -- but I'm not entirely sure of the best way to grab or store this information in a generic/standard/reusable way. (I'm figuring on storing it in the session and then deleting it once it's pulled back out; if that seems like a bad idea, that's something else to address.)
Is there a standard "best practices" or cookbook way to do this?
(One wrinkle: these forms are being submitted via POST.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我不禁想到,在一个通常需要 15 分钟以上操作之间间隔的应用程序中强制执行 15 分钟超时存在根本性缺陷。
尽管如此,我还是会考虑重写
Catalyst::Plugin::Session->delete_session
方法,以便$c->request-> 的任何内容都可以被删除。 body_parameters
被序列化并保存(可能保存到数据库)以供以后恢复。 您可能需要对 POST 参数进行一些基本检查,以确保它们符合您的预期。同样,create_session 需要负责从数据库中提取这些数据,并使其可用于原始表单操作。
这看起来确实是一个混乱的情况,我倾向于重复我的第一句话...
更新:
无论您使用
delete_session
还是auto
,矛盾的问题仍然存在:您无法将此信息存储在会话中,因为超时事件会破坏会话。 您必须将其存储在更永久的位置,以便它在会话重新初始化后仍然存在。Catalyst::Plugin::Session
本身正在使用 可存储,并且您应该能够使用以下内容:基础表可能具有 (user CHAR(x), formitems TEXT) 或类似内容。 也许是一个时间戳,这样就不会恢复任何过时的内容。 您可能还想存储正在处理的操作,以确保检索到的表单项属于正确的表单。 您比我更了解您的应用程序的问题。
I can't help thinking that there's a fundamental flaw in mandating a 15 minute timeout in an app that routinely requires >15 minutes between actions.
Be that as it may, I would look at over-riding the
Catalyst::Plugin::Session->delete_session
method so that any contents of$c->request->body_parameters
are serialised and saved (presumably to the database) for later recovery. You would probably want some rudimentary check of the POST arguments to ensure they're what you're expecting.Similarly,
create_session
needs to take responsibility for pulling this data back out of the database and making it available to the original form action.It does seem like a messy situation, and I'm inclined to repeat my first sentence...
UPDATE:
Whether you use
delete_session
orauto
, the paradoxical issue remains: you can't store this info in the session because the time-out event will destroy the session. You've got to store it somewhere more permanent so it survives the session re-initialization.Catalyst::Plugin::Session
itself is using Storable, and you should be able to with something along these lines:The underlying table probably has (user CHAR(x), formitems TEXT) or similar. Perhaps a timestamp so that nothing too stale gets recovered. You might also want to store the action you were processing, to be sure the retrieved form items belong to the right form. You know the issues for your app better than me.
我会将表单数据存储为模型中的某种每用户数据。
Catalyst::Plugin::Session::PerUser 是这样做的一种方法(尽管有点黑客)。 我建议仅使用会话插件进行身份验证并将所有状态信息存储在存储用户数据的模型中。
我完全同意 RET 的观点,即 15 分钟的限制在这种情况下似乎确实适得其反。
I would store the form data as some sort of per user data in the model.
Catalyst::Plugin::Session::PerUser is one way of doing that (albeit somewhat hackishly). I would reccomend using the session plugin only for authentication and storing all the state info in the model that stores your user data instead.
And I totally agree with RET's opinion that the 15 minute limit seems really counter productive in this context.
我在 CPAN 中搜索完全不相关的内容时发现了这一点。
Catalyst::Plugin::Wizard 旨在完全满足您的需求。 该文档表明它可以重定向到登录页面,同时保留先前操作的状态。
注意:我没有使用过它,所以不能保证它的有效性。
I came across this whilst searching CPAN for something entirely unrelated.
Catalyst::Plugin::Wizard purports to do exactly what you need. The documentation suggests it can redirect to a login page whilst retaining the state of the previous action.
NB: I haven't used it, so can't vouch for its effectiveness.
最后,我们最终在 auto() 中获取待处理的请求(URL+参数),对其进行序列化和加密,并通过登录页面上的隐藏表单元素传递它。 如果我们收到填充了隐藏元素的登录请求,我们将对其进行解密和反序列化,然后进行适当的重定向(确保通过标准的“此用户可以执行此操作吗”代码路径)。
In the end, we ended up grabbing the pending request (URL+params) in the auto(), serializing and encrypting it, and passing it via a hidden form element on the login page. If we got a login request with the hidden element populated, we decrypted and deserialized it and then redirected appropriately (making sure to pass through the standard "can this user do this thing" code paths).
您始终可以在客户端上使用一些 javascript,通过每隔几分钟发出一个小请求来防止会话过期。
或者,您可以在发布表单之前让 AJAX 检查活动会话,并在需要时向用户显示新的登录框。
You could always have some javascript on the client that keeps the session from expiring by making a small request every few minutes.
Or you could have AJAX check for an active session before posting the form and presenting the user with a new login box at that time if needed.