PHP:$ _SESSION-将临时使用的数据存储在$ _SESSION变量中的优缺点是什么

时间:2020-03-05 18:57:21  来源:igfitidea点击:

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

解决方案

回答

$ _SESSION项目存储在会话中,默认情况下,它保留在磁盘上。无需像我们一样制作自己的阵列并将其填充到" dataentry"阵列条目中。我们可以只使用$ _SESSION ['pcode'],$ _ SESSION ['modules']等。

就像我说的那样,会话存储在磁盘上,而指向该会话的指针则存储在cookie中。因此,用户无法轻松获得会话数据。

回答

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

就像其他任何东西一样,要小心,始终清理用户输入,尤其是如果要将用户输入放入$ _SESSION变量中,然后在SQL查询中使用该变量。

回答

在决定存储临时数据的位置时,需要考虑一些因素。会话存储非常适合单个用户的数据。如果我们发现默认的基于文件的会话存储处理程序效率低下,则可以实施其他操作,可能使用数据库或者后端的内存缓存类型。有关更多信息,请参见session_set_save_handler。

我发现在用户的会话中存储通用数据是一种不好的做法。有更好的存储数据的位置,这些数据将被多个用户频繁访问,通过将这些数据存储在会话中,我们将为需要此数据的每个用户复制数据。在示例中,我们可能为此波浪数据(基于wave_id)设置了另一种类型的存储引擎,该存储引擎并不专门与用户的会话绑定。这样,我们将一次拉取数据并将其存储在多个用户可以访问数据而无需再次拉取的位置。

回答

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

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

回答

如果我们在自己的服务器上运行,或者在没人能窥探服务器上文件/内存的环境中,则会话数据是安全的。它们存储在服务器上,只是一个标识cookie发送到客户端。问题是,其他人当然可以抢走cookie并假冒其他人。使用HTTPS并确保不将会话ID放在URL中,可以使用户免受大多数此类问题的影响。 (如果我们不注意的话,XSS可能仍可用于抓取cookie,也请参见Jeef Atwoods的相关文章。)

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

回答

这是很常见的事情,并且会话通常比连续数据库命中要快。它们也相当安全,因为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'])."'";

回答

Zend Framework具有用于会话数据管理的有用库,该库有助于有效期和安全性(用于验证码之类的东西)。他们对会议也有有用的解释。参见http://framework.zend.com/manual/en/zend.session.html

回答

那么,Session变量实际上是在访问者访问网站的整个时间中都可以使用这些变量的唯一方法(也许是最有效的方法),用户没有真正的方法来编辑它们(除了我们网站中的漏洞利用程序之外)代码或者PHP解释器中),因此它们相当安全。

这是存储可由用户更改的设置的好方法,因为我们可以在会话开始时从数据库中读取一次设置,并且该设置可在整个会话中使用,因此,如果设置需要进行进一步的数据库调用进行更改,当然,正如我们在代码中所显示的那样,很容易找出设置是否已经存在或者是否需要从数据库中提取设置。

我想不出其他任何方式来安全地存储临时变量(因为cookie可以轻松修改,并且在大多数情况下这是不希望的),因此$ _SESSION将是一种方法。

回答

改善输入验证的另一种方法是强制转换_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的程度吗?

即,请参阅" REST简介"中的"无状态通信"段落。

"REST mandates that state be either
  turned into resource state, or kept on
  the client. In other words, a server
  should not have to retain some sort of
  communication state for any of the
  clients it communicates with beyond a
  single request."

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

因此,在情况下," wave_id"是GET的明智资源,但我们是否真的要将其存储在SESSION中? memcached当然是我们缓存对象Resource的解决方案吗?

回答

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

  • $ _SESSION`数据将在session.gc_maxlifetime闲置几秒钟后过期。
  • 我们必须记住为每个将使用会话数据的脚本调用session_start()
  • 通过在多个服务器上进行负载平衡来扩展网站可能是一个问题,因为每次都需要将用户定向到同一台服务器。通过" Sticky Sessions"解决此问题。

回答

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