我知道两种在页面之间传递参数的方法:
- 使用 POST 和
<input type="hidden">
- 使用
$_SESSION["variable_name"]
我发现第二种方式更容易,但我想知道它是否和第一种一样安全,因为在我看到的大多数教程中,他们使用第一种方式。
有什么重要的理由更喜欢第一种方式而不是第二种方式吗?
要了解其中的区别,让我们详细了解每种解决方案的工作原理及其安全风险。在此示例中,我们将存储用户的页面浏览次数。
我们启动会话,增加计数器并将其存储在$_SESSION
数组中:
<?php
session_start();
if(!isset($_SESSION["pageviews"]))
{
$_SESSION["pageviews"] = 0;
}
$_SESSION["pageviews"]++;
?>
当用户第一次访问该页面时,PHP 会生成一个如下所示的随机会话标识符,并要求浏览器将此 ID 存储在 cookie 中:
fh4giqncq25ntgs7gjunvj6i33
在服务器上,它将存储并记住一个pageviews
变量,其值1
属于会话 ID fh4giqncq25ntgs7gjunvj6i33
。
下次用户访问该页面时,他或她的浏览器将连同请求一起发送上一个会话 ID(假设 cookie 尚未过期或被删除)。PHP 然后识别这个 ID,并用 填充$_SESSION
数组pageviews = 1
,然后递增它:pageviews = 2
在安全方面,请考虑以下问题:
用户是否能够读取存储的数据?否- 客户端看到的唯一内容是 cookie 中的随机会话 ID;数据本身存储在服务器上。
用户是否能够更改或操作存储的数据?同样,不——如果会话 ID 在浏览器中被更改,PHP 将无法再将浏览器与存储的数据联系起来。在这种最坏的情况下,用户将获得一个新会话,以pageviews = 1
.
会话的主要安全风险是会话劫持,即攻击者设法从其他人的浏览器获取会话 ID,然后将其呈现给服务器,从而冒充其他用户。在我们的示例中,这没有多大意义,因为我们只存储了页面浏览次数;但是,大多数站点使用会话来跟踪哪个用户从哪个浏览器登录。在这种情况下,窃取其他人的会话将意味着访问他们的帐户。
在这种情况下,我们有一个带有隐藏字段的表单:
<form action="..." method="post">
<input type="hidden" name="pageviews" value="<?php print($pageviews); ?>" />
...
</form>
在服务器上,我们pageviews
从中检索变量$_POST
并对其进行递增:
<?php
$pageviews = @$_POST["pageviews"];
$pageviews++;
?>
因此,我们实际上不是将其存储在服务器上,而是将数据向下发送到客户端,并期望它在后续请求中返回。除了它仅适用于POST请求这一事实之外,让我们看看此解决方案与安全相关的缺点:
用户是否能够读取存储的数据?是的——它直接进入 HTML 代码中的浏览器。
用户是否能够更改或操作存储的数据?是的——没有什么可以阻止用户在他或她的浏览器中打开开发者工具并将隐藏的值更改为他或她喜欢的任何值。提交表单后,服务器获取更改后的数据。
问题<input type="hidden">
在于您不能信任客户端,因此您必须验证在每个请求中获得的数据。在某些情况下这样做可能是合理的,例如填写多页表单,但即使这样通常也可以通过会话更好地解决。
通过持久化数据$_SESSION
通常比使用更安全<input type="hidden">
,因为会话数据存储在服务器上,因此无法被客户端篡改。只有一个随机会话标识符在 cookie 中发送到浏览器,该 cookie 将服务器上的数据与该特定浏览器联系起来。