php 如何检测用户是否为同一个会话打开两个选项卡?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5574970/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 21:50:45  来源:igfitidea点击:

How to detect if user open two tabs for same session?

phpsessiontabs

提问by darnpunk

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.

我已经使用 CakePHP 完成了一个预订应用程序,它在结帐页面之前涉及几个步骤。在这些步骤之间,我将信息存储在会话中。

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.

它的工作原理是第 1 步要求他们填写信息。进入步骤2时,步骤1中的信息会保存到会话对象中。当他们继续执行其他步骤时,该过程会重复。最后结帐时,所有数据都会保存到数据库中。

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.

假设他们在 Tab A 和 Tab B 中打开了应用程序的两个实例。在 Tab A 中,他们输入了第 1 步中的详细信息并继续执行第 2 步。然后用户在 Tab B 中执行相同的操作。

At the last step when the user does a checkout, information in Tab A is the same as in Tab B.

最后一步,当用户结账时,Tab A 中的信息与 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?

当用户尝试在选项卡 B 中打开另一个实例时,有没有办法检测并提示用户先在选项卡 A 中完成预订表单?

采纳答案by pufos

1.The same problem (and solution) : https://sites.google.com/site/sarittechworld/track-client-windows

1.同样的问题(和解决方案):https: //sites.google.com/site/sarittechworld/track-client-windows

2.You can send information by POST or GET

2.您可以通过POST或GET方式发送信息

回答by Hymanson Gabbard

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.

当然,您可以使用客户端轮询脚本来实现这一点。在 JavaScript 中,您可以生成一个窗口 ID,该 ID 可以是任何内容,只要它保证唯一即可。让 JS 将 Ajax 调用者发送到服务器上的端点,该端点只比较 ID 和会话。在任何时候,如果您有两个不同的“windowID”值,您知道它们必须为同一个会话打开窗口。

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.

您可以将其作为会话中的数组存储在服务器端,或者您甚至可以将其完全存储在客户端的 cookie 中。如果您选择这样做,您的客户端轮询器将只查看 cookie 值,如果它包含两个不同的值,就会出现问题。但是 Cookie 不太理想,因为它们增加了请求/响应周期的权重,并且您必须设置一种机制来在用户卸载页面时清除当前页面的值。

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.

对于服务器端实现,您只需要将当前 windowID 与链接或帖子一起发送,以便服务器可以从会话中清除 windowID。但是,这些都无法防止用户同时打开 Firefox 会话和 Chrome 会话。

回答by Guttsy

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.

您可以在第 1 步开始时将会话标记为已开始。确保服务器端他们遵循正确的步骤(即在完成第 1 步后他们不会返回到第 1 步,除非他们专门单击一个链接来这样做。)基本上,跟踪他们在服务器上的当前步骤并更新它如所须。如果用户做了一些意想不到的事情,你可以让他们选择重新开始。

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.

对于跨浏览器支持,您需要将其与用户帐户或持续存在的内容相关联。

回答by Hymanson Gabbard

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.

正如 Benjamin 指出的那样,您可以通过为每个窗口提供一个 ID 来实现这一点,然后您将每个请求报告给服务器。如果要启用多窗口用例,我认为这是最合理的方法。

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.

我认为您不需要通过 ajax 轮询服务器来执行此操作。只要对服务器的每个请求都包含窗口 ID,您就可以明确服务器端将请求与哪个会话相关联。这意味着您的服务器端代码必须更改以将窗口 ID 作为会话的一部分包含在内。

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?

然而,这种方法有严重的缺点。例如,如果用户同时关闭 Tab A 和 Tab B,然后打开一个新的 Tab C……会发生什么?他们应该重新连接哪一组数据?

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.

你可以通过本地存储来做到这一点,顺便说一句。如果您在客户端生成一个随机 ID 并通过调用将其推送到本地存储,window.localStorage.setItem('window_id', <my_random_id_here>);那么您可以在页面加载时检查此值。如果页面加载时该值存在,则您将获得一个非常清晰的指示,表明至少有一个其他窗口处于打开状态。您必须确保在页面卸载时删除此值,否则死会话可能会触发误报。