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

问题描述:

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

您的SQL查询容易受到SQL注入攻击。例如,某人可以放置'?wave_id = wave_id',查询将选择所有行。 (这在DELETE,INSERT和UPDATE查询中更糟糕。)在这种情况下,您应该编写代码以确保它是一个数字,最简单的方法是intval() – 2008-09-16 22:20:44

那么会话变量实际上是唯一一种让访问者在网站*问这些变量的唯一方式(也可能是最有效的方法)之一,用户无法编辑它们(除了代码中的漏洞或PHP解释器中的漏洞),因此它们相当安全。

这是一种存储用户可以更改设置的好方法,因为您可以在会话开始时从数据库读取一次设置,并且可以在整个会话中使用这些设置,您只需要创建更多的数据库如果设置发生变化,则会发生调用,当然,正如您在代码中所显示的那样,查明设置是否已存在或是否需要从数据库中提取这些设置是微不足道的。

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

+3

“它们相当安全”仅当它是专用服务器时才是真实的。共享托管在同一台机器上的其他用户可以访问php会​​话数据。 – Jacco 2009-04-20 15:44:05

$ _SESSION项目存储在会话中,这是在默认情况下,保留在磁盘上。不需要像你一样制作自己的数组并将其填入“数据入口”数组条目中。你可以使用$ _SESSION ['pcode'],$ _SESSION ['modules']等等。

就像我说过的,会话存储在磁盘上,会话指针存储在cookie中。用户因此不能容易地查看会话数据。

+1

只需使用多维数组 $ _SESSION [ mystuff'] ['mydata'] ='blah'; – conmulligan 2008-09-16 22:31:41

+0

@conmulligan:当然,但除了你放在那里的东西之外,没有什么会进入会议。您可能会将$ _SESSION与$ _SERVER混淆。 – nsayer 2008-09-17 22:24:59

我使用这种方法很公平,我没有看到任何问题。与Cookie不同,数据不存储在客户端,这通常是一个很大的错误。

就像任何事情一样,小心你总是在清理用户输入,特别是如果你将用户输入放入$ _SESSION变量,然后在SQL查询中使用该变量。

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

我发现将常见数据存储在用户会话中是一种不好的做法。有更好的地方可以存储将被多个用户频繁访问的数据,并通过将这些数据存储在会话中,您将为每个需要此数据的用户复制数据。在你的例子中,你可能为这个波形数据建立了一个不同类型的存储引擎(基于wave_id),这个数据不是专门针对用户会话的。通过这种方式,您可以将数据向下拖动一次,然后将其存储在某个用户可以访问数据的地方,而无需再次拖动。

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

  • 某人劫持一个会话是可能的,所以如果您打算使用它来跟踪用户授权,请注意。阅读this了解更多信息。
  • 它可能是一个非常懒惰的方式来保持数据。不要只是将所有内容都放在会话中,以便以后不必查询。
  • 如果您打算在会话中存储对象,那么在下次请求启动会话之前,需要将其类文件包含在内,否则您需要配置自动加载器。

如果您正在自己的服务器上运行,或者在没有人可以监听服务器上的文件/内存的环境中运行,则会话数据是安全的。它们存储在服务器上,只是发送给客户端的身份识别码。问题是,如果其他人可以抓取cookie并冒充其他人,当然。使用HTTPS并确保不要将会话ID放入URL中,这样可以让您的用户免于大部分问题的困扰。 (如果您不小心,XSS可能仍然用于抓取cookie,请参阅Jeef Atwoods post on this。)

至于要存储在会话变量中的内容如果要在其他页面上再次引用它,就像购物篮一样,但如果它只是用于生成此页面结果的临时数据,就不会放在那里,就像当前查看帖子的标签列表一样。会话是针对每个用户的持久数据。

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

唯一的问题是,您需要记住在某些更改时重建会话条目。而且,如果拥有该会话的用户以外的任何用户更改了此密钥,则无法通知系统刷新该会话密钥。可能不是什么大不了的,但你应该注意的事情。

我一直使用会话变量来为用户存储信息。我没有看到任何性能问题。会话数据根据Cookie进行提取(如果您关闭了Cookie,则会提供PHPSESSID)。我不认为它比任何其他基于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'])."'"; 
+0

谢谢!这个桩溢出让我以惊人的速度学习,我很惊讶。 – markus 2008-09-16 22:31:01

Zend框架具有会话数据管理有用的库与到期和安全性(像验证码的东西)帮助。他们对会议也有有用的解释。请参阅http://framework.zend.com/manual/en/zend.session.html

另一种方式的方式改善输入验证是投_GET [“wave_id”]变量:

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

我假定wave_id是整数,并且仅存在一个答案。

我发现会话是非常有用的,但有几个注意事项:

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

2)如果你正在建立,需要您可能希望将它发送到会议之前对数据进行加密,并解密使用它非常严密的安全措施较高的价值体系。注意:这可能会产生太多开销,具体取决于您的流量/服务器容量。

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

$ _SESSION机构会使用Cookie。

在Firefox(也许是新的IE浏览器,我没有检查自己)的情况下,这意味着会话在打开的标签之间共享。这不是你默认的预期。这意味着会话不再是“单个窗口/用户专用的东西”。

例如,如果你已经打开了两个标签来访问您的网站,使用第一个选项卡不是记录为根,你会在另外一个获得root权限。

那可真是不方便,特别是如果你的代码的电子邮件客户端或其他什么东西(如网上商店)。在这种情况下,您必须手动管理会话或在URL中引入不断重新生成的密钥或执行其他操作。

你可能想考虑一下这是怎样的REST-ful?

即见“沟通无状态”段落“A Brief Introduction to REST” ......

“REST授权该缔约国要么 变成资源状态,或保留在 客户端。换句话说,服务器 不应该保留某种 通信状态对于任何 客户它超出 单个请求传达的。”

(或任何在*上的其他链接,REST的)

所以你的情况,在“wave_id”是一个明智的资源得到的,但你真的希望将其存储在SESSION?当然,memcached是缓存对象资源的解决方案吗?

使用会议的其他一些缺点:后的session.gc_maxlifetime闲置

  1. $_SESSION数据将到期。
  2. 您必须记得为每个将使用会话数据的脚本调用session_start()
  3. 通过在多个服务器上进行负载均衡来扩展网站可能是一个问题,因为用户每次都需要定向到同一个服务器。用“粘滞会话”解决这个问题。

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