没有 cookie 的 PHP 会话

Posted

技术标签:

【中文标题】没有 cookie 的 PHP 会话【英文标题】:PHP session without cookies 【发布时间】:2011-04-14 00:58:37 【问题描述】:

有没有一种方法可以在不放置会话 cookie 的情况下在 php 中启动持久会话?是否有其他方法可以跨页面维护会话,例如基于 IP 地址的解决方案?

我问的原因是,尽管大多数用户都打开了 cookie,但我想看看是否有一种方法可以让登录系统为禁用它的用户工作(尽管我个人认为禁用 cookie 只是不必要的偏执狂)。

【问题讨论】:

【参考方案1】:

我认为要求您的用户启用 Cookie 并不过分。当人们完全关闭它们时,我觉得很愚蠢。

否则,您可以将 session.use_only_cookies 设置为“0”,以强制将会话 ID 附加到 php.ini 中的 URL。然而,这种方法有几个缺点。主要是保持 URL 中的状态,而不是 Cookie 标头。如果用户复制并粘贴他们所在页面的 URL,而其他人点击它,他们将使用同一个会话。

<?php
     ini_set("session.use_cookies", 0);
     ini_set("session.use_only_cookies", 0);
     ini_set("session.use_trans_sid", 1);
     ini_set("session.cache_limiter", "");
     session_start();

【讨论】:

我相信 OP 希望将 session.use_cookies 设置为 1 并且需要注意的是,这些设置不会改变 PHP 代码中的 JS 超链接和 Location 标头。 "(现在连蜘蛛都可以吃饼干了)"哇。 :) 我说让他们,即使它给了他们爱的把手。 Facebook 应用在 IFrame 中运行,在 IE 上不允许存储 cookie(默认安全设置) @w43L marco.org/2007/04/27/…【参考方案2】:

您可以将session.use_trans_sid 的 ini-Value 设置为 true 以激活将会话 ID 附加到每个 URL。看看this。

为了安全起见,您应该将会话限制为创建会话的 IP。但这并不完全安全,因为具有相同 IP(例如,在代理之后)的人可以重复使用相同的会话。

【讨论】:

【参考方案3】:

您可以在 URL 中使用会话 ID,并通过以下方式禁用 cookie:

ini_set('session.use_cookies', 0);
ini_set('session.use_only_cookies', 0);
ini_set('session.use_trans_sid', 1);
session_start();
// IP check
if($_SESSION['ip_check'] != $_SERVER['REMOTE_ADDR'])
   session_regenerate_id();
   session_destroy();
   session_start();

$_SESSION['ip_check'] = $_SERVER['REMOTE_ADDR'];
// session stuff

注意:在 URL 中使用会话 ID 是非常不受欢迎的。使用无线网卡旅行时,IP 地址可能会发生变化,并且代理服务器具有相同的 IP 地址。单击“旧 URL”(使用旧会话 ID)时很容易损坏。

您可能还对创建自己的会话处理函数(结合数据库)感兴趣。您将忽略会话 ID,并将其绑定到 IP 地址。 (参见http://php.net/manual/en/function.session-set-save-handler.php 中的示例)

参考资料:

http://php.net/manual/en/session.configuration.php

【讨论】:

绑定到一个 IP 地址似乎是一个不好的方法。一些(公司?)用户可能位于代理后面,其中多个用户可以拥有相同的 IP 地址。 @Leander Wooord!这可能会导致非常糟糕的情况,整个公司/家庭/学生宿舍都可以访问您用户的帐户。 德国最大的 ISP (Telekom) 甚至有自己的代理,很多人都在使用。因此,在最坏的情况下,一个漏洞 ISP 网络将使用一个帐户。这真的很烦人,因为如果您不想依赖 X-HTTP-Forwarded-For 标头,它几乎不可能禁止 IP 地址。【参考方案4】:

您可以创建一个数据库记录或临时文件,并在每次页面加载时根据请求检查$_SERVER vars。这是一个安全风险,但有足够多的变量(查看列表here),您可能会觉得您已经将劫持的机会降至可接受的水平;只有您知道您的应用需要有多安全。

【讨论】:

【参考方案5】:

您可以在数据库中保存每个 IP 的会话 ID:

创建一个包含三个字段的 mysql 表:session_id、ip 和唯一临时密钥(用于登录用户)或您喜欢的任何其他条件。然后关闭会话cookie并使用_trans_sid。

然后根据这个新表编写代码来管理会话行为!

session_start()将session_id保存在表中,稍后从表中接收(通过IP和任何其他条件),然后调用

session_id($in_table_session_id);

有关更多信息和完整指南,请参阅:https://gist.github.com/mimrahe/77415f4a9e238c313bbe8c42f8a6b7fe

【讨论】:

同样,这是通过 IP 绑定的,并不完全有效,尤其是对于多个用户共享相同 IP 的范围(例如大学、公司或组织代理等) @T30 “有关更多信息和完整指南,请参阅:”链接不正确——发帖者已“死亡”。你有这个链接吗?谢谢。 不,抱歉,在archive.org 上快速搜索也没有任何结果...【参考方案6】:

如果我想这样做,我会在 html 代码中添加会话 ID 作为注释标记,并使用和配置 PHP 代码以使用包含在 HTML 代码中的会话 ID。我认为这样做比使用用户 IP 或在 URL 中添加会话 ID 更相关。

【讨论】:

+1 似乎需要做很多工作,但它绝对是 url-session-ids 和 cookie 的解决方法。如果您有每个表单生成的随机字符串,可能会更安全。结合表单的随机字符串和隐藏的会话 ID,您几乎可以肯定授权用户正在发出请求。我知道 ror 使用这样的东西。 guides.rubyonrails.org/form_helpers.html【参考方案7】:

对此的正确答案是否定的。使用 cookie 之外的任何变量组合都是不安全的。

想一想:当用户 FIRST 请求一个页面时,服务器会发送该页面以及一个独特的值,上面写着“HTTP 是无状态的,请保留它,以便下次调用时我知道它是'你'”。这意味着,那个人,在那个浏览器(不管标签页)中,在那个时候运行,有一个唯一的令牌。

当且仅当他们成功登录时,该令牌现在可以绑定到服务器端的会话。令牌应该是如此长且随机,以至于没有人能及时猜到。

多个浏览器可能使用相同的 IP 地址。多人可以拥有完全相同的用户代理。 cookie 是唯一有效的存储系统。

实际上还有另一种方法,那就是将唯一令牌添加到返回到服务器的每个链接以及所有 AJAX 调用,例如 ?PHPSESSID=my-unique-token-189481958 - 但编写代码很麻烦.

【讨论】:

【参考方案8】:

您也可以仅通过会话 ID 和时间不使用 Cookie 登录,但您必须在成功登录后直接将它们写入数据库。

我在 index.php 中有这样的东西,它总是会生成一个新的会话 id 如果条件未验证,则基于时间和旧会话 ID。

if ($_SESSION['id'] != $row['session'] || time() > $row['sessiontime']) 
    session_destroy();
    session_start();
    session_regenerate_id();

    
$_SESSION['id'] = session_id();

我在数据库中使用 2 个变量作为 id 和 time。

在登录窗口中,我从 $_SESSION['id'] 变量中读取会话 ID,然后增加时间并将两者都发送到数据库。

【讨论】:

以上是关于没有 cookie 的 PHP 会话的主要内容,如果未能解决你的问题,请参考以下文章

PHP cURL 没有存储会话 cookie...如何解决这个问题?

php cookie 和会话变量和 ip 地址

Redis PHP 会话不持久

如何使用php制作涉及会话cookie的注销页面?

PHP 会话与 Cookies [重复]

Ngrok 无法提供 PHP 会话 cookie: