使用会话变量而不是隐藏的输入字段是否更安全


Is it more secure to use a session variable instead of a hidden input field?

我知道两种在页面之间传递参数的方法:

  1. 使用开机自检和<input type="hidden">
  2. 使用$_SESSION["variable_name"]

发现第二种方法更容易,但我想知道它是否与第一种方法一样安全,因为在我看到的大多数教程中,他们使用第一种方法。

有什么重要的理由偏爱第一种方式而不是第二种方式吗?

为了理解其中的区别,让我们详细介绍每个解决方案的工作原理及其安全风险。在此示例中,我们将存储用户的页面浏览量。

$_SESSION

我们启动会话,递增计数器并将其存储在$_SESSION数组中:

<?php
session_start();
if(!isset($_SESSION["pageviews"]))
{
    $_SESSION["pageviews"] = 0;
}
$_SESSION["pageviews"]++;
?>

当用户第一次访问此页面时,PHP 将生成如下所示的随机会话标识符,并要求浏览器将此 ID 存储在 cookie 中:

fh4giqncq25ntgs7gjunvj6i33

在服务器上,它将存储并记住有一个值为1pageviews变量属于会话ID fh4giqncq25ntgs7gjunvj6i33

下次用户访问该页面时,他或她的浏览器将发送上一个会话 ID 以及请求(假设 cookie 尚未过期或删除(。然后 PHP 识别此 ID,并用 pageviews = 1 填充$_SESSION数组,然后递增它:pageviews = 2

在安全性方面,请考虑以下问题:

用户是否能够读取存储的数据?否 – 客户端唯一看到的是 cookie 中的随机会话 ID;数据本身存储在服务器上。

用户是否能够更改或操作存储的数据?同样,no – 如果在浏览器中更改了会话 ID,PHP 将无法再将浏览器绑定到存储的数据。在这种最坏的情况下,用户将获得一个新会话,从 pageviews = 1 开始。

会话

的主要安全风险是会话劫持,当攻击者以某种方式设法从其他人的浏览器获取会话 ID,然后将其呈现给服务器,从而冒充其他用户时。在我们的示例中,这没有多大意义,因为我们只存储页面查看计数;但是,大多数站点使用会话来跟踪哪个用户从哪个浏览器登录。在这种情况下,窃取其他人的会话将意味着可以访问他们的帐户。

隐藏字段

在本例中,我们有一个带有隐藏字段的表单:

<form action="..." method="post">
    <input type="hidden" name="pageviews" value="<?php print($pageviews); ?>" />
    ...
</form>

在服务器上,我们从$_POST中检索pageviews变量并将其递增:

<?php
$pageviews = @$_POST["pageviews"];
$pageviews++;
?>

因此,我们本质上不是将数据存储在服务器上,而是将数据发送到客户端,并期望在后续请求中返回。除了它仅适用于 POST 请求这一事实之外,让我们看看此解决方案与安全相关的缺点:

用户是否能够读取存储的数据?是的 - 它直接进入 HTML 代码中的浏览器。

用户是否能够更改或操作存储的数据?是的 - 没有什么可以阻止用户在他或她的浏览器中打开开发人员工具并将隐藏值更改为他或她喜欢的任何值。提交表单后,服务器将获取更改后的数据。

<input type="hidden">的问题在于你不能信任客户端,所以你必须验证你在每个请求中获得的数据。在某些情况下这样做可能是合理的,例如填写多页表单,但即使这样通常也可以通过会话更好地解决。

总结

通过 $_SESSION 持久化数据通常比使用 <input type="hidden"> 更安全,因为会话数据存储在服务器上,因此客户端无法篡改。在cookie中,只有随机会话标识符被发送到浏览器,该cookie将服务器上的数据与该特定浏览器相关联。