【问题标题】:Creating custom PHP Session handler?创建自定义 PHP 会话处理程序?
【发布时间】:2011-06-30 18:11:24
【问题描述】:

现在我在使用 PHP 的本机会话管理和创建自己的(基于 MySQL)的会话系统之间陷入困境,我对这两者有一些疑问。

  1. 除了会话固定和会话劫持之外,使用 PHP 的本地会话处理代码还有哪些其他问题?这两个问题都很容易解决,但我一直看到人们编写自己的系统来处理会话,所以我想知道为什么。

  2. 基于 MySQL 的会话处理程序会比 PHP 的本机会话更快吗?假设一个标准(不是“内存”)表。

  3. 使用session_set_save_handler 有什么主要缺点吗?我可以让它在很大程度上符合我的标准(除了命名)。另外,我个人喜欢使用 $_SESSION['blah'] = 'blah'$session->assign('blah', 'blah') 的想法,或者在某种程度上。

  4. 有什么好的 php 会话资源我应该看看吗?我上一次参加会议是在 10 年前,所以我的知识有点停滞。谷歌和 Stackoverflow 搜索产生了很多基本的,显然写得很糟糕的教程和示例(将用户名 + md5(密码)存储在 cookie 中,然后创建一个会话!),所以我希望这里的人有一些合法的、更高级的资源。

  5. 无论我如何选择,我都将强制使用仅 cookie 的方法。这有什么问题吗?此代码将支持的站点在平均安全环境中拥有普通用户。我记得上次我使用 session 时这是一个大问题,但是使用 in-url session 的想法让我非常紧张。

【问题讨论】:

  • 你想用这个会话做什么?

标签: php session


【解决方案1】:

2) 的答案是 - id 取决于。 让我解释一下:为了使会话处理程序正常运行,您确实应该实现某种类型的锁定和解锁机制。 MySQL方便地具有lock table和unclock table的功能。如果您没有在会话处理程序中实现表锁定,那么您可能会在基于 ajax 的请求中出现竞争条件。相信我,你不想要那些。

阅读这篇解释race condition in custom session handler的详细文章:

那么,如果您按照应有的方式将 LOCK TABLE 和 UNLOCK TABLE 添加到每个会话调用中,那么您的自定义会话处理程序将变得有点慢。

你可以做的一件事是使用 HEAP 表来存储会话。这意味着数据将仅存储在 RAM 中,永远不会写入磁盘。这将工作得非常快,但如果服务器出现故障,所有会话数据都会丢失。

如果您同意服务器宕机时会话丢失的可能性,那么您应该使用 memcache 作为会话处理程序。 Memcache 已经具备使用 php 会话处理程序所需的所有功能,您只需安装 memcache 服务器,安装 php 的 memcache 扩展,然后在 php.ini 中添加类似这样的内容

[Session]
; Handler used to store/retrieve data.
; http://php.net/session.save-handler
;session.save_handler = files
session.save_handler = memcache
session.save_path="tcp://127.0.0.1:11215?persistent=1"

这肯定会比基于默认文件的会话处理程序快得多

使用 MySQL 作为会话处理程序的优点是您可以编写自定义类来做其他事情,当数据保存到会话时会做额外的事情。例如,假设您将代表 USER 的对象保存到会话中。您可以使用自定义会话处理程序从该 OBJECT 中提取用户名、用户 ID、头像并将它们写入 MySQL SESSION 表中的专用列,从而可以轻松显示谁在线

如果您的会话处理程序中不需要额外的方法,那么没有理由使用 MySQL 来存储会话数据

【讨论】:

  • 谢谢,这正是我所追求的信息类型。我实际上正在考虑使用 HEAP 表,但是我们在一个相当流行的站点(高峰时间约 500 个会话)上谈论什么样的内存使用情况,具有足够的会话 ID 列、IP 列、时间分配列和数据(Varchar 还是文本?)列?关于 memcache - 我喜欢这个想法,但是这将用于共享主机,还有没有办法在 Dreamhost 或 Hostgator 上使用 memcache 作为会话处理程序?
  • 是的,memcache 可以在远程机器上使用,你所有的前端服务器都可以使用同一个 memcache 服务器。只需在所有 php.ini 文件中使用相同的内存缓存服务器 IP 地址即可。我在一个相当繁忙的网站(每天大约 100,000 次页面浏览量)上使用 memcache,它只分配给 memcache 的 256MB 工作正常
  • 如果您只想编辑某些行,则不需要锁定整个表格。
  • @Gumbo,这取决于存储类型。 MyISAM 没有行级锁定,因此您在写入或修改单行时总是锁定整个表。 InnoDB 具有行级锁定,但 InnoDB 通常比 MyISAM 慢,对于会话存储不是一个好主意
  • “如果您不在会话处理程序中实现表锁定,那么您可能会在基于 ajax 的请求中出现竞争条件。相信我,您不想要这些。”但是如果你确实实现了锁定,那么即使它们只是读取请求,请求也会按顺序运行。例如,如果您在会话中唯一拥有的是一个 user_id,并且您同时对数据进行了五个请求,那么它们一次运行一个并锁定,一次运行 5 个而不锁定。实际上,用户同时登录两次的情况永远不会发生,因此会话踩踏不是什么大问题。
【解决方案2】:

PHP 应用程序在请求之间丢失会话信息。由于斯坦福有多个网络服务器,不同的请求可能会被定向到不同的服务器,因此会话信息经常会丢失。

斯坦福大学的网络基础设施由多个网络服务器组成,它们彼此不共享会话数据。因此,请求之间的会话可能会丢失。使用 MySQL 可以有效地解决这个问题,因为所有会话数据都直接进出数据库服务器而不是 Web 集群。在数据库中存储会话还具有增加隐私和安全性的效果,因为访问数据库需要身份验证。我们建议斯坦福大学所有可以访问 MySQL 的 Web 开发人员都使用这种方法进行会话处理。

转自http://www.stanford.edu/dept/its/communications/webservices/wiki/index.php/How_to_use_MySQL-based_sessions

This 可以帮到你。

【讨论】:

【解决方案3】:

大多数语言标准库的会话实现只支持基本的键值关联,其中键由客户端提供(即会话 ID),值存储在服务器端(即会话存储)然后关联应客户要求。

除此之外的任何内容(尤其是安全措施)也超出了键值关联的基本会话机制,需要添加。尤其是这些安全措施大多伴随着故障:如何判断某个会话的请求的真实性?通过IP地址?通过用户代理识别?或两者?或者根本没有会话身份验证?这始终是开发人员需要处理的安全性和可用性之间的权衡。

但是,如果我需要实现会话处理程序,我不仅会寻求纯粹的速度,而且——根据要求——也会寻求可靠性。 Memcache 可能很快,但如果服务器崩溃,所有会话数据都会丢失。与此相反,数据库更可靠,但与 memcache 相比,可能存在速度上的缺点。但是,除非您自己测试和基准测试,否则您不会知道。您甚至可以使用两个不同的会话处理程序来处理不同的会话可靠性级别(unreliable in memcache 和 reliable in MySQL/files)。

但这一切都取决于您的要求。

【讨论】:

    【解决方案4】:

    它们都是很好的方法,使用 MySQL 有一些缺点,在某些情况下,如果操作不正确或负载太高,流量水平实际上可能会使服务器崩溃!

    鉴于标准会话已得到妥善处理,我个人建议仅使用它们并加密您不希望黑客看到的数据。

    如果没有适当的预防措施,cookie 的使用是不安全的。除非您需要“记住我”,否则请坚持使用会话! :)

    编辑

    不要使用 MD5,它的加密和解密能力都很差……我建议对数据进行加盐并一起加密。

    $salt = 'dsasda90742308408324708324832';
    $password = sha1(sha1(md5('username').md5($salt));
    

    这种加密不会很快被解密,我认为现在不可能。

    【讨论】:

    • 谢谢,虽然我指的是用于存储会话 ID 的 cookie(通过服务器端检查分配给该 ID 的 IP),至于 MD5 - 这是一个笑话(而 MD5 是哈希,而不是加密)...我在谈论一些谈论会话的教程,也提到了这一点。我个人将 phpass 与每个用户的盐一起使用。我也不会让任何用户看到任何散列密码。不过感谢您的关注:)
    • MD5 不是加密,因此无法解密。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多