如何检测用户是否为同一会话打开两个选项卡?
我已经使用 CakePHP 完成了一个预订应用程序,其中涉及结账页面之前的几个步骤。在这些步骤之间,我将信息存储在会话中。
其工作原理是,第 1 步要求他们填写信息。当进入步骤2时,步骤1中的信息将被保存到会话对象中。当他们继续执行其他步骤时,该过程会重复。最后,当他们结帐时,所有数据都会保存到数据库中。
如果用户在浏览器中打开应用程序的一个实例,一切都会正常运行。但是,一旦他们在同一浏览器中为同一应用程序打开另一个页面或另一个选项卡,就会出现问题。
假设他们在选项卡 A 和选项卡 B 中打开了两个应用程序实例。在选项卡 A 中,他们输入了步骤 1 中的详细信息,然后继续执行步骤 2。然后用户在选项卡 B 中执行相同的操作。
在最后一步,当用户进行结帐时,选项卡 A 中的信息与选项卡 B 中的信息相同。
现在,我只能认为最好的方法是防止用户在两个浏览器实例中打开相同的应用程序。
当用户尝试在选项卡 B 中打开另一个实例时,是否有一种方法可以检测并提示用户首先在选项卡 A 中完成预订表单?
I've done a booking application done using CakePHP which involves a few steps before the checkout page. In between these steps I store the information in the session.
How it works is that Step 1 requires them to fill in their information. When going to Step 2, the information in Step 1 will be saved into the session object. As they proceed in the other steps, the process repeats. At the end when they checkout, all the data is then saved to the database.
Everything works great if the user opens one instance of the application in the browser. But once they have another page or another tab opened for the same application in the same browser, problem happens.
Let's say they have two instance of the application open in Tab A and Tab B. In Tab A they entered the details in Step 1 and proceed to Step 2. Then the user does the same thing in Tab B.
At the last step when the user does a checkout, information in Tab A is the same as in Tab B.
Right now, I can only think the best way is to prevent the user from opening the same application in two browser instance.
Is there a way to detect and prompt the user to complete the booking form in Tab A first when they try to open another instance in Tab B?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
1.同样的问题(和解决方案):https://sites.google。 com/site/sarittechworld/track-client-windows
2.您可以通过POST或GET方式发送信息
1.The same problem (and solution) : https://sites.google.com/site/sarittechworld/track-client-windows
2.You can send information by POST or GET
您可以在步骤 1 首次启动时将会话标记为已启动。确保服务器端他们遵循正确的步骤(即,在完成步骤 1 后,他们不会返回到步骤 1,除非他们专门单击链接来执行此操作。)基本上,跟踪服务器上当前的步骤并更新它根据需要。如果用户做了意外的事情,您可以给他们重新开始的选项。
我想知道表单上带有时间戳的隐藏字段是否有帮助。不过有点相同的想法。
警告:此过程可能会破坏浏览器后退按钮的本质。我讨厌自己让这种情况发生在我的一个项目中。
对于跨浏览器支持,您需要将其与用户帐户或持续存在的内容相关联。
You could mark a session as started when step 1 is first started. Make sure server-side that they follow the right steps (i.e. they don't return to step 1 after step 1 has been completed unless they specifically click a link to do so.) Basically, track their current step on the server and update it as needed. In the event the user does something unexpected, you could give them the option to start over.
I'm wondering if hidden fields with timestamps on your forms might help. Kinda the same idea though.
Caveat: this process might break the essence of your browser's back button. I hate myself for letting that happen in one of my projects.
For cross-browser support, you'd need to have it associated with a user account or something that persists.
当然,您可以使用客户端轮询器脚本来实现此目的。在 JavaScript 中,您可以生成一个窗口 ID,它可以是任何值,只要保证其唯一即可。让 JS 使 Ajax 调用者连接到服务器上的端点,该端点除了比较 ID 和会话外什么也不做。在任何时候,如果您有两个不同的“windowID”值,您就知道它们必须为同一会话打开窗口。
您可以将其作为会话中的数组存储在服务器端,甚至可以将其完全存储在客户端的 cookie 中。如果您选择这样做,您的客户端轮询器只会查看 cookie 值,如果它包含两个不同的值,则表示出现问题。不过,Cookie 不太理想,因为它们会增加请求/响应周期的权重,并且您必须设置一种机制来在用户卸载页面时清除当前页面的值。
对于服务器端实现,您只需要发送当前的 windowID 以及链接或帖子,以便服务器可以从会话中清除 windowID。但这些都无法防止用户同时打开 Firefox 会话和 Chrome 会话。
Sure, you can achieve this with a client-side poller script. In JavaScript, you can generate a window ID that can be anything as long as its guaranteed to be unique. Have the JS make Ajax callers to an endpoint on the server that does nothing but compare IDs and session. At any point if you have two different "windowID" values, you know they have to have to windows open for the same session.
You could store this on the server side as an array in the session or you could even store it entirely on the client side in a cookie. If you chose to do that, your client side poller would just look at the cookie value and if it contains two different values, something is amiss. Cookies are a little less ideal though because they add weight to the request/response cycle and you'd have to setup an mechanism to clear the value of the current page when the user unloads the page.
For the server-side implementation, you would just need to send the current windowID along with link or post so that the server can clear the windowID from the session. None of this would protect against the user having a Firefox session and a Chrome session open at once though.
正如本杰明所指出的,您可以通过提供每个窗口的 ID 来做到这一点,然后将其通过每个请求报告给服务器。如果您想启用多窗口用例,我认为这是最合理的方法。
我认为你不需要通过 ajax 轮询服务器来做到这一点。只要对服务器的每个请求都包含窗口 ID,您就可以消除服务器端与请求关联的会话的歧义。这意味着您的服务器端代码必须更改以将窗口 ID 作为会话的一部分包含在内。
然而,这种方法有严重的缺陷。例如,如果用户关闭选项卡 A 和选项卡 B,然后打开新的选项卡 C...会发生什么?他们应该重新连接哪组数据?
如果您需要防止多个选项卡的状态混合,那么将用户限制为单个选项卡的方法听起来相当合理。
顺便说一句,您可以通过本地存储来做到这一点。如果您在客户端上生成随机 ID 并通过诸如
window.localStorage.setItem('window_id',);
之类的调用将其推送到本地存储,那么您可以在页面加载。如果页面加载时该值存在,则您将得到一个非常清晰的指示,表明至少还有一个其他窗口已打开。您必须确保在页面卸载时删除此值,否则死会话可能会触发误报。As Benjamin pointed out, you can do this by coming up with a per-window ID which you then report to the server with each request. If you want to enable the multiple window use case, I think this is the most reasonable approach.
I don't think you need to poll the server via ajax to do this though. As long as every request to the server includes the window ID, you can disambiguate what session on the server side to associate the request with. That will mean that your server-side code has to change to include the window ID as part of the session.
However, that approach has serious drawbacks. For instance, if the user closes both Tab A and Tab B, and then opens up a new Tab C... what happens? Which set of data should they reconnect with?
The approach of restricting the user to a single tab sounds pretty reasonable if you need to prevent the intermingling of multiple tabs worth of state.
You can do this via Local Storage, btw. If you generate a random ID on the client and push it into Local Storage via a call like
window.localStorage.setItem('window_id', <my_random_id_here>);
then you can check for this value on page load. If the value exists when the page loads, you've got a pretty clear indicator that at least one other window is open. You'll have to make sure to remove this value on page unload, otherwise dead sessions might trigger false positives.