32

我最近开始经常做的一件事是在任务开始时检索一些数据并将其存储在 $_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;
}
4

15 回答 15

20

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

这是一种存储用户可以更改的设置的好方法,因为您可以在会话开始时从数据库中读取一次设置,并且它可用于整个会话,您只需在设置时进行进一步的数据库调用已更改,当然,正如您在代码中显示的那样,找出设置是否已经存在或是否需要从数据库中提取它们是微不足道的。

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

于 2008-09-16T22:26:16.180 回答
6

我一直使用会话变量来为用户存储信息。我没有看到任何性能问题。会话数据是基于 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'])."'";
于 2008-09-16T22:24:43.173 回答
6

$_SESSION 机制正在使用 cookie。

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

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

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

于 2008-10-13T05:53:08.160 回答
3

在决定将临时数据存储在何处时,您需要考虑几个因素。会话存储非常适合特定于单个用户的数据。如果您发现默认的基于文件的会话存储处理程序效率低下,您可以实现其他东西,可能使用数据库或 memcache 类型的后端。有关更多信息,请参阅session_set_save_handler

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

于 2008-09-16T22:19:31.673 回答
3

如果您在自己的服务器上运行,或者在没有人可以窥探服务器上的文件/内存的环境中运行,则会话数据是安全的。它们存储在服务器上,只是发送给客户端的标识 cookie。当然,问题是其他人是否可以抢走 cookie 并冒充其他人。使用 HTTPS 并确保不将会话 ID 放在 URL 中应该可以使您的用户免受大多数这些问题的影响。(如果你不小心的话,XSS 可能仍会被用来抓取 cookie,请参阅Jeef Atwoods 的帖子。)

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

于 2008-09-16T22:21:10.827 回答
2

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

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

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

将要

于 2008-09-16T22:47:31.263 回答
2

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

  1. $_SESSION数据将在session.gc_maxlifetime秒不活动后过期。
  2. 您必须记住调用session_start()将使用会话数据的每个脚本。
  3. 通过在多个服务器上进行负载平衡来扩展网站可能是一个问题,因为每次都需要将用户定向到同一台服务器。用“Sticky Sessions”解决这个问题。
于 2009-04-20T11:20:38.193 回答
1

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

就像我说的,会话存储在磁盘上,指向会话的指针存储在 cookie 中。因此,用户不能轻易获得会话数据。

于 2008-09-16T22:16:34.630 回答
1

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

  • 有人可能会劫持会话,因此如果您要使用它来跟踪用户授权,请小心。阅读内容以获取更多信息。
  • 保存数据可能是一种非常懒惰的方式。不要只是将所有内容都扔到会话中,以便您以后不必查询它。
  • 如果您要在会话中存储对象,则需要在下一个请求启动会话之前包含它们的类文件,或者您需要配置一个自动加载器。
于 2008-09-16T22:20:49.020 回答
1

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

于 2008-09-16T22:25:58.537 回答
1

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

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

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

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

于 2008-09-17T00:03:11.050 回答
1

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

即参见“ A Brief Introduction to REST ”中的“无状态通信”段落...

“REST 要求状态要么转换为资源状态,要么保留在客户端上。换句话说,服务器不应该为任何与其通信的客户端保留某种通信状态,而不是单个请求。”

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

所以在你的情况下,'wave_id' 是一个合理的 GET 资源,但你真的想将它存储在 SESSION 中吗?memcached肯定是您缓存对象资源的解决方案吗?

于 2009-03-11T13:05:00.493 回答
0

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

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

于 2008-09-16T22:17:00.137 回答
0

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

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

于 2008-09-16T22:23:04.753 回答
0

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

于 2009-04-29T16:15:33.687 回答