繁体   English   中英

您如何检测并防止用户使用php / javascript从多个浏览器选项卡访问Web应用程序?

[英]How do you detect and prevent a user from accessing a web app from multiple browser tabs using php/javascript?

我有一个Web应用程序,我想限制为单个浏览器选项卡或窗口。 因此,想法是用户登录,并且如果他们在选项卡/窗口中打开链接或打开新的浏览器选项卡/窗口,则会终止其会话。 我知道很多人对此表示反对,但这就是应用程序需要的方式。

控制器检查用户是否通过以下方式登录:

if (!isset($_SESSION['user_logged_in'])) {
    Session::destroy();
        header('location: '.URL.'login');
}

我曾尝试将$ _SESSION ['user_logged_in']设置为false(如果为true),但是显然您只需要一页就可以了。

打开新的浏览器选项卡或窗口时,是否可以破坏会话? 我猜大概是jquery / javascript,但没有跨过那一面。

不幸的是,这是非常复杂的。
几乎不可能做到真正的跨浏览器并得到每个浏览器的支持。

从技术上讲,从服务器的角度来看,每个新的浏览器选项卡都与后者没有区别。 他们也共享cookie和会话。

唯一不同的是JavaScript会话。 举个例子:一个完全基于AJAX的站点。 第一页面始终是登录页面。 然后,AJAX改变了一切。 例如,如果您敢于用此站点打开另一个选项卡,它将打开第一页,该页面总是默认注销。 这样可以实现,但是非常复杂。

诸如localStorage类的新技术堆栈可能使之成为可能,您可以在其中在localStorage发送消息的选项卡之间进行通信。 但这不是完全跨浏览器的,并非所有浏览器版本都支持。

因此,如果您只能选择有限的最新浏览器,那么请使用localStoragepostMessage

仅仅背诵Oleg所说的话,这将是非常困难的,因为HTTP是无状态的并且浏览器选项卡共享数据。 一种可能的实现方式可能是在前端,但是需要提供一组非常具体的情况,并且可以轻松地绕开它们。 如果应用程序是SPA,并且主体仅加载一次,则可能会在主体加载上生成密钥,并在每次请求时发送该密钥。 然后,如果重新加载了正文(例如在新选项卡或新窗口中),则可以生成一个新密钥,该密钥将启动一个新会话。

但是,真正的问题是为什么您要这样做。 您的用户体验将受到损害,并且不存在真正的安全性提升。

我有一些解决方案,希望与您分享。
要将用户限制为每个会话一个选项卡,可以使用cookie。 我在这里描述了如何构建Web应用程序以实现该目标。

  1. 每次Web模块需要呈现auth / login页面时,请创建并存储具有给定名称的cookie。 我们称它为browserName。 Cookie的值必须是一个生成的值。 如果您的编程语言是java,则可以使用java.util.UUID。
  2. 当浏览器完成加载您的身份验证/登录页面时,请使用生成的cookie值设置浏览器的名称。 您必须知道如何使用JavaScript读取Cookie。
  3. 每次用户加载除auth / login页面之外的其他页面时,请检查当前浏览器的名称是否是存储在cookie中的名称。 如果它们不同,则提示用户,然后您可以运行一个片段以重置会话并重定向到auth / login页面。

下面是实现我所说的示例。

  1. 在您的登录页面之前运行的方法中添加的片段
    Map<String, Object> v$params = new TreeMap<>(); v$params.put("path", "/"); FacesContext.getCurrentInstance() .getExternalContext() .addResponseCookie("browserName", UUID.randomUUID().toString(), v$params);
  2. 迷你JavaScript库,可帮助您处理Cookie和其他内容。 将其全局添加到您的webapp中。

 /** * http://stackoverflow.com/questions/5639346/shortest-function-for-reading-a-cookie-in-javascript */ (function() { function readCookie(name, c, C, i) { if (cookies) { return cookies[name]; } c = document.cookie.split('; '); cookies = {}; for (i = c.length - 1; i >= 0; i--) { C = c[i].split('='); cookies[C[0]] = C[1]; } return cookies[name]; } window.readCookie = readCookie; // or expose it however you want })(); // function read_cookie(k,r){return(r=RegExp('(^|; // )'+encodeURIComponent(k)+'=([^;]*)').exec(document.cookie))?r[2]:null;} function read_cookie(k) { return (document.cookie.match('(^|; )' + k + '=([^;]*)') || 0)[2]; } /** * To be called in login page only */ function setupWebPage(){ window.name = read_cookie("browserName"); } /** * To be called in another pages */ function checkWebPageSettings(){ var curWinName = window.name; var setWinName = read_cookie("browserName"); if( curWinName != setWinName){ /** * You may redirect the user to a proper page telling him that * your application doesn't support multi tab/window. From this page, * the user may decide to go back to the previous page ou loggout in * other to have a new session in the current browser's tab or window */ alert('Please go back to your previous page !'); } } 

  1. 将此添加到您的登录页面
    <script type="text/javascript"> setupWebPage(); </script>
  2. 将此添加到您的其他页面模板
    <script type="text/javascript"> checkWebPageSettings(); </script>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM