繁体   English   中英

使用特定于标签的Cookie而不使用sessionStorage或任何HTML5功能

[英]Tab specific cookies without using sessionStorage or any HTML5 features

我感兴趣的是让用户能够在我的网络应用程序上登录并注销多个用户会话cookie。 目前,身份验证是标准的,并且唯一标识符允许我在用户访问我们的站点时对其进行身份验证,如果他们提供了cookie中可用的身份验证令牌。 典型用例适用于如果用户从一个选项卡注销,它会将其从另一个选项卡中注销。 现在,它要求用户从两个独特的浏览器实例登录,以便能够登录到两个不同的帐户。

是否有非HTML5方式(使用标准javascript cookie)具有特定于标签的cookie标识符? 我假设没有明确的方法来解决这个问题,这需要从后端进行某种黑客+合作。 如果有一个没有使用HTML5的解决方案,那将是理想的。

你不能。

有办法处理这种情况,但没有一种是简单的。

如果你愿意,你必须告诉用户这样做: 如何极客

从文档: 使用sessionStorage存储的数据不会在浏览器选项卡中保留,即使两个选项卡都包含来自同一域来源的网页。 换句话说, sessionStorage数据不仅限于调用页面的域和目录,而且还包含页面所在的浏览器选项卡。与会话cookie相对照,会话cookie将数据从选项卡保留到选项卡。

一段时间后我实现了类似的行为。 所以,我做的是这样的:

  1. 为此,您需要在URL中携带sessionId或作为页面内容的一部分。
  2. 加载登录页面时,删除sessionId cookie。
  3. 提交登录时,服务器会在URL中为您提供登录页面以及sessionId,或者作为html响应正文的一部分。
  4. 从现在开始,在每次服务器调用之前,将会话cookie设置为您在URL或页面内容中具有的cookie。
  5. 因此,每个选项卡都会在任何服务器调用之前设置自己的cookie,这将使请求在服务器上与正确的会话着陆。

在此之前,只有您使用相对URL时,此解决方案才有效! (用于图像,链接甚至Ajax调用)

像在任何普通场景中一样使用会话进行一次小的更改。 您将通过每个会话ID识别一台机器(浏览器),而不是使用每个会话ID识别用户。 因此,当请求到达服务器时,它会识别在该计算机上使用您的网站的一群用户。 每个用户都有自己的子标识符(可以是顺序计数器或随机数)。 简单来说,您的会话数据(由Cookie中的会话ID标识)包含一个关联数组。 该阵列的每个条目保存由子标识符标识的一个特定用户的会话数据。 例如,在PHP中,如果您的用户的子标识符是user0 ,那么您可以访问此用户的会话数据,如:

<?php
session_start();
$user_data = $_SESSION['user0'];

接下来是如何传递用户的子标识符。

您可以使用webserver的URL重写。 您需要提出一个可以被视为普通文件夹名称的模式,而没有像这样的文件夹。 例如:

RewriteEngine On
RewriteRule ^user(\d+)\/(.*)$ $2?sub_id=$1 [QSA,L]

在此示例中,您不允许使用user0user1等任何文件夹。如果某些请求要求http://domain.com/user0/index.php ,则会将其重写为http://domain.com/index.php?sub_id=user0 现在在index.php你将拥有:

<?php
session_start();
$user_data = $_SESSION[$_REQUEST['sub_id']];

从这一点开始你应该使用$user_data而不是$_SESSION 唯一剩下的就是如何第一次生成子标识符。 这相对容易,您可以:

<?php
session_start();
if (!isset($_REQUEST['sub_id'])) {
    $sub_id = 0;
    while (isset($_SESSION["user{$sub_id}"])) {
        $sub_id++;
    }
    $_SESSION["user{$sub_id}"] = array();
    header("Location: /user{$sub_id}".$_SERVER['REQUEST_URI']);
    die();
}
else {
    $user_data = $_SESSION[$_REQUEST['sub_id']];
}

最后,只有当您的所有网址都是相对的时,一切都会有效! 不以/user0/开头的每个绝对URL将被视为新用户,并将导致会话中的新条目。

这种方法的好处是,只要URL已经相对解决,您当前的代码将以最小的努力工作。

这是一个简单的示例,说明如何创建用户可以登录多个帐户的系统。 这不是安全检查,必须添加。 这段代码可以更好地编写和优化。

inc.php

https://github.com/maksa9/multiple-user-login/blob/master/inc.php

此文件包含在每个php脚本中。

此部分检查记录了哪个用户以及哪个帐户处于活动状态。 以下是根据活动帐户创建php脚本的正确路径的函数

// check which user is logged and which account is active
if(isset($_GET['user'])) $id_user = (int)$_GET['user'];
if($id_user > 0)
{
    if(isset($_SESSION['user'][$id_user]))
    {        
        $user_name = $_SESSION['user'][$id_user]['name'];
        $user_email = $_SESSION['user'][$id_user]['email'];                
    }
    else
        gotToLoginForm();
}

// If the user id is not specified and there is a user session, finds another id
if($id_user == 0 and isset($_SESSION['user']))
{    
    $sess = $_SESSION['user'];

    $id_user = (int)key($sess);

    if(isset($_SESSION['user'][$id_user]))
    {        
        $user_name = $_SESSION['user'][$id_user]['name'];
        $user_email = $_SESSION['user'][$id_user]['email'];  

        define('ID_USER',$id_user);

        gotToIndex();              
    }
    else
        gotToLoginForm();

}

define('ID_USER',$id_user);

loginform.php

https://github.com/maksa9/multiple-user-login/blob/master/loginform.php

使用post方法登录的简单表单。

的login.php

https://github.com/maksa9/multiple-user-login/blob/master/login.php

登录用户。 模拟对数据库的查询。

if(isset($_POST['email']))
    if(isset($_POST['pass']))
    {
        $email = $_POST['email'];
        $pass = $_POST['pass'];

        $id_user = 0;

        // simulates a query to the database
        if($email === 'test1@test.com' and $pass === '111')
        {
            $id_user = 1;
            $name='John Doe';
        }
        if($email === 'test2@test.com' and $pass === '222')
        {
            $id_user = 2;
            $name = 'Doe John';
        }

        // login user
        if($id_user > 0)
        {
            // checks if the user is already logged
            if( !isset($_SESSION['user'][$id_user]))
            {
                $_SESSION['user'][$id_user] = array('email'=>$email, 'name'=>$name);
            }

            //go to main page 
            $page = ROOT.'user/'.$id_user.'/index.php';            
            header('Location: '.$page);
            exit;

        }        
    }

的index.php

https://github.com/maksa9/multiple-user-login/blob/master/index.php

应用程序的主页面。

<div>
    <h1>Welcome: <?php echo $user_name ?> (<?php echo $user_email ?>) [<?php echo $id_user ?>]</h1>


    <p><a href="<?php echo returnUrl('swap.php',$id_user)  ?>">Choose an account</a></p>    
    <p><a href="<?php echo returnUrl('loginform.php',$id_user)  ?>">Login with the another account</a></p>        
    <p><a href="<?php echo returnUrl('logout.php',$id_user)  ?>">Log out</a></p>

</div>

swap.php

https://github.com/maksa9/multiple-user-login/blob/master/swap.php

允许用户选择帐户。

foreach($_SESSION['user'] as $idus => $userA)
{
    echo '<p><a href="'.returnUrl('index.php',$idus).'">'.$userA['name'].' ('.$userA['email'].') ['.$idus.']</a></p>';
}

logout.php

https://github.com/maksa9/multiple-user-login/blob/master/logout.php

注销用户。 检查活动用户帐户并重定向(如果有)。

unset($_SESSION['user'][ID_USER]);

if(count($_SESSION['user']) == 0) 
    unset($_SESSION['user']);


// checks for active user accounts and redirects them if any
if(isset($_SESSION['user']))
{        
    $sess = $_SESSION['user'];

    $id_user = (int)key($sess);

    if(isset($_SESSION['user'][$id_user]))
    {            
        $page = ROOT.'user/'.$id_user.'/index.php';            
        header('Location: '.$page);
        exit;               
    }        
}    

的.htaccess

https://github.com/maksa9/multiple-user-login/blob/master/.htaccess

Options +FollowSymlinks
RewriteEngine On

RewriteRule ^user\/([0-9]*)\/index.php$ index.php?user=$1 [NC,L]
RewriteRule ^user\/([0-9]*)\/logout.php$ logout.php?user=$1 [NC,L]
RewriteRule ^user\/([0-9]*)\/login.php$ login.php?user=$1 [NC,L]
RewriteRule ^user\/([0-9]*)\/loginform.php$ loginform.php?user=$1 [NC,L]
RewriteRule ^user\/([0-9]*)\/swap.php$ swap.php?user=$1 [NC,L]

RewriteRule ^user\/$ index.php [NC,L]
RewriteRule ^user$ index.php [NC,L]

你不能

创建cookie时,可以通过设置其“根域”来控制其可见性。 然后,属于该根的任何URL都可以访问它。 例如,root可以设置为“example.com”,然后cookie将可用于“www.example.com”或“xyz.example.com”或“example.com”中的站点。 这可能用于允许相关页面相互“通信”。 无法将根域设置为“顶级”域,例如“.com”或“.co.uk”,因为这样可以广泛访问cookie。

默认情况下,cookie对其域中的所有路径都是可见的,但在创建时,它们可以被限制到给定的子路径 - 例如“www.example.com/images”。

所以任何具有相同根域的选项卡都可以访问该cookie。

会话cookie是服务器特定的AFAIK,因此您可以为同一服务器设置不同的DNS名称,例如子域名,如:session1.myserver.com,session2.myserver.com,session3.myserver.com

那么@ dm4web的回答是正确的,但你必须留意他的安全警告。 您可以做的最好的事情是采取双向方法。

方向一

Regular Login.
Create a Unique session ID and pass it via the URL.

方向二

Check Session via i) Logged In User and ii) Check Session ID via URL Param

现在,我们来举个例子:

$usrname: Fool
$psswd: dm4web

PHP代码

session_start();
//all inputs should be sanitized
$sql = "SELECT * FROM `users` WHERE `usrname`='".$usrname."' AND `psswd` = '".$psswd."'":
$dbh = new PDO('odbc:db', 'db2inst1', 'ibmdb2');
$count = $dbh->exec($sql);
if($count > 0){
 //Guy is logged in
 $a = session_id();
 //**Use this $a in every URL parameter under current session**
}
else {
 //Go f**k yourself >> to the user ;)
}

但是你应该注意到你不能直接跳转到那个用户/传递匹配方案。 首先,您必须确保了解用户是否已登录。 此外,基于PHP的SESSION Cookie,你可以理解这一点

  1. 如果计算机上有活动登录
  2. 如果URL上有活动登录[从session_id事件中获取$ a]

您在所有情况下都匹配 URL参数,与SESSION cookie交叉引用并继续!

祝好运! 如果您还有其他问题,请与我们联系!

暂无
暂无

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

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