PHP:$_SESSION - 在 $_SESSION 变量中存储临时使用的数据有哪些优点和缺点

StackOverflow https://stackoverflow.com/questions/77826

  •  09-06-2019
  •  | 
  •  

我最近开始更频繁做的一件事是 检索一些数据 在任务开始时 并将其存储在 $_SESSION['myDataForTheTask'] 中.

现在这样做似乎很方便,但我对使用这种方法的性能、安全风险或类似情况一无所知。这是由具有更多专业知识的程序员经常做的事情还是更多是业余的事情?

例如:

if (!isset($_SESSION['dataentry']))
{
    $query_taskinfo = "SELECT participationcode, modulearray, wavenum FROM mng_wave WHERE wave_id=" . mysql_real_escape_string($_GET['wave_id']);
    $result_taskinfo = $db->query($query_taskinfo);
    $row_taskinfo = $result_taskinfo->fetch_row();

        $dataentry = array("pcode" => $row_taskinfo[0], "modules" => $row_taskinfo[1], "data_id" => 0, "wavenum" => $row_taskinfo[2], "prequest" => FALSE, "highlight" => array());

        $_SESSION['dataentry'] = $dataentry;
}
有帮助吗?

解决方案

好吧,会话变量实际上是使这些变量在访问者访问网站的整个时间内可用的唯一方法之一(并且可能是最有效的),用户没有真正的方法来编辑它们(除了您的漏洞利用程序之外)。代码或 PHP 解释器中),因此它们相当安全。

这是存储用户可以更改的设置的好方法,因为您可以在会话开始时从数据库中读取一次设置,并且该设置可用于整个会话,如果设置有效,您只需要进行进一步的数据库调用已更改,当然,正如您在代码中所示,查明设置是否已存在或是否需要从数据库中提取是很简单的。

我想不出任何其他安全存储临时变量的方法(因为 cookie 很容易被修改,这在大多数情况下是不可取的),所以 $_SESSION 是最好的选择

其他提示

$_SESSION机制正在使用cookie。

对于 Firefox(也许还有新的 IE,我没有检查自己),这意味着 会话在打开的选项卡之间共享. 。默认情况下,这不是您所期望的。这意味着会话不再是“特定于单个窗口/用户的东西”。

例如,如果您打开了两个选项卡来访问您的站点,那么使用第一个选项卡以 root 身份登录,您将在另一个选项卡中获得 root 权限。

这确实很不方便,特别是当您编写电子邮件客户端或其他东西(例如电子商店)时。在这种情况下,您将必须手动管理会话或在 URL 中引入不断重新生成的密钥或执行其他操作。

我一直使用会话变量来为用户存储信息。我没有看到任何性能问题。会话数据是基于cookie(或 PHPSESSID 如果您关闭了cookie)。我不认为它比任何其他基于 cookie 的身份验证更具安全风险,并且可能比在用户 cookie 中存储实际数据更安全。

只是想让您知道,您的 SQL 语句确实存在安全问题:

SELECT participationcode, modulearray, wavenum FROM mng_wave WHERE wave_id=".$_GET['wave_id'];

你应该 从来没有,我再说一遍,从来没有, ,获取用户提供的数据并使用它来运行 SQL 语句,而无需先对其进行清理。我将其用引号括起来并添加函数 mysql_real_escape_string(). 。这将保护您免受大多数攻击。所以你的行看起来像:

$query_taskinfo = "SELECT participationcode, modulearray, wavenum FROM mng_wave WHERE wave_id='".mysql_real_escape_string($_GET['wave_id'])."'";

在决定临时数据的存储位置时,您需要考虑几个因素。会话存储非常适合特定于单个用户的数据。如果您发现默认的基于文件的会话存储处理程序效率低下,您可以实现其他方法,可能使用数据库或内存缓存类型的后端。看 会话设置保存处理程序 了解更多信息。

我发现在用户会话中存储通用数据是一种不好的做法。有更好的位置来存储多个用户经常访问的数据,通过将此数据存储在会话中,您将为每个需要此数据的用户复制数据。在您的示例中,您可以为此波形数据(基于wave_id)设置不同类型的存储引擎,该存储引擎不专门与用户会话相关联。这样,您只需将数据拉下来一次,然后将其存储在多个用户可以访问数据的位置,而无需再次拉动。

如果您在自己的服务器上运行,或者在没有人可以窥探服务器上的文件/内存的环境中,则会话数据是安全的。它们存储在服务器上,并且只是发送到客户端的识别 cookie。当然,问题是其他人是否可以抢走 cookie 并冒充其他人。使用 HTTPS 并确保不将会话 ID 放入 URL 中应该可以让您的用户免受大多数此类问题的影响。(如果你不小心的话,XSS可能仍然会被用来抢夺cookie,请参阅 杰夫·阿特伍兹对此发表了帖子 也。)

至于在会话变量中存储什么内容,如果您想在另一个页面(例如购物篮)上再次引用它,请将数据放在那里,但如果它只是用于生成此结果的临时数据,则不要将其放在那里页面,例如当前查看的帖子的标签列表。会话用于每个用户的持久数据。

改进输入验证的另一种方法是强制转换 _GET['wave_id'] 变量:

$query_taskinfo = "SELECT participationcode, modulearray, wavenum FROM mng_wave WHERE wave_id=".(int)$_GET['wave_id']." LIMIT 1";

我假设 wave_id 是一个整数,并且只有一个答案。

将要

使用会话的其他一些缺点:

  1. $_SESSION 数据将在以下时间后过期 会话.gc_maxlifetime 不活动的秒数。
  2. 你必须记得打电话 session_start() 对于每个将使用会话数据的脚本。
  3. 通过在多个服务器上进行负载平衡来扩展网站可能会出现问题,因为用户每次都需要被定向到同一台服务器。使用“粘性会话”解决此问题。

$_SESSION 项存储在会话中,默认情况下,会话保存在磁盘上。无需像您一样创建自己的数组并将其填充到“dataentry”数组条目中。您可以只使用 $_SESSION['pcode']、$_SESSION['modules'] 等。

正如我所说,会话存储在磁盘上,指向会话的指针存储在 cookie 中。因此,用户无法轻松获取会话数据。

IMO,在会话中存储内容是完全可以接受的。这是使数据持久化的好方法。在许多情况下,它也比将所有内容存储在 cookie 中更安全。以下是一些问题:

  • 有人可能会劫持会话,因此如果您要使用它来跟踪用户授权,请务必小心。读 了解更多信息。
  • 这可能是一种非常懒惰的数据保存方式。不要只是将所有内容都放入会话中,这样您就不必稍后查询它。
  • 如果您要在会话中存储对象,则在下一个请求启动会话之前需要包含它们的类文件,或者您需要配置自动加载器。

Zend Framework 有一个有用的会话数据管理库,有助于过期和安全(对于验证码之类的东西)。他们还对会议进行了有用的解释。看 http://framework.zend.com/manual/en/zend.session.html

我发现会议非常有用,但需要注意以下几点:

1) PHP 可能会将您的会话存储在 tmp 文件夹或服务器上其他用户可以访问的其他目录中。您可以通过转到 php.ini 文件来更改存储会话的目录。

2) 如果您正在设置一个需要非常严格的安全性的高价值系统,您可能需要在将数据发送到会话之前对其进行加密,并解密以使用它。笔记:这可能会产生过多的开销,具体取决于您的流量/服务器容量。

3)我发现session_destroy();不会立即删除会话,您仍然需要等待 PHP 垃圾收集器来清理会话。您可以在 php.ini 文件中更改垃圾收集器运行的频率。但似乎仍然不太可靠,更多信息 http://www.captain.at/howto-php-sessions.php

您可能想考虑一下这有多 REST 式?

IE。请参阅“无状态通信”段落REST 简介"...

“休息要求状态变为资源状态,要么将其保存在客户端上。换句话说,服务器不必为其与单个请求超出单个请求的任何客户保留某种通信状态。”

(或维基百科上的任何其他链接 休息)

因此,在您的情况下,“wave_id”是一个明智的 GET 资源,但您真的想将其存储在 SESSION 中吗?一定 内存缓存 您的解决方案是缓存对象资源吗?

我经常使用这种方法,我不认为它有任何问题。与 cookie 不同,数据不存储在客户端,这通常是一个很大的错误。

但与任何事情一样,请注意始终清理用户输入,特别是如果您将用户输入放入 $_SESSION 变量中,然后在 SQL 查询中使用该变量。

这是相当常见的事情,并且会话通常比连续的数据库命中更快。它们也相当安全,因为 PHP 开发人员努力防止会话劫持。

唯一的问题是,当发生变化时,您需要记住重建会话条目。而且,如果会话所有者以外的用户进行了任何更改,导致需要刷新此密钥,则没有简单的方法可以通知系统刷新此会话密钥。可能没什么大不了的,但你应该注意一些事情。

$_SESSION 在安全方面非常有用,因为它是当用户活跃在您的页面上时存储信息的服务器端方式,因此很难破解,除非您的实际 php 文件或服务器存在被利用的弱点。一种非常好的实现是存储一个变量来确认用户已登录,并且仅在确认登录后才允许执行操作。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top