首页 > 解决方案 > 将 URL 引用者(来源)限制为根 URL 或同一页面

问题描述

我正在为我的网站构建一个 2FA 系统。

verify.php 由同一页面上的 2 个部分组成,由 IF THEN ELSE 语句分隔

我试图限制热链接和对 verify.php 的直接访问为此,我试图将其放在我的页面顶部:

$ref1 = $_SERVER['HTTP_REFERER'];
$ref2 = $_SERVER['PHP_SELF'];

if($ref1 !== 'https://example.com/' || $ref1 !== $ref2) {
  header('Location: https://example.com');
  session_destroy();
}

对 verify.php 的直接访问效果很好,它被重定向到根目录。不幸的是,当用户输入他的电子邮件并单击发送时,我得到了相同的结果。verify.php 的 part2 应该出现,但被重定向到根目录。

如何修改我的顶级 php 代码片段,以便识别相同的页面来源并且脚本可以完成?

标签: php

解决方案


您可以做的是使用会话来检查客户是否首先访问了您网站的另一个页面。

index.php您允许访问的起始页面上,您可以输入以下内容:

<?php

session_start();

$_SESSION['verifyStatus'] = "AccessGranded";

然后在verify.php页面上您可以执行以下操作:

<?php

session_start();

if (!isset($_SESSION['verifyStatus']) || 
    ($_SESSION['verifyStatus'] != "AccessGranded")) {
     header('Location: https://example.com');
     die;
}

所有这一切都是检查客户端是否在index.php页面之前访问过该verify.php页面。它不检查它是否就在它之前。

为了确保这index.php是上一页,我们需要对这个想法进行一些扩展。我将为此使用随机令牌。在index.php你使用:

<?php

session_start();

$_SESSION['verifyToken'] = bin2hex(random_bytes(16));

在同一页面上,当您链接到时,verify.php您必须提供此令牌作为参数。像这样:

echo '<a href="verify.php?token='.$_SESSION['verifyToken'].'">Go to verify</a>';

然后我们客户端进入verify.php页面,你有两个版本的令牌,一个是 in $_SESSION['verifyToken'],一个是 in $_GET['token']。它们必须相同。所以verify.php你可以这样做:

<?php

session_start();

if (!isset($_SESSION['verifyToken']) ||
    !isset($_GET['token']) ||   
    ($_SESSION['verifyToken'] != $_GET['token'])) {
     header('Location: https://example.com');
     die;
}

现在它或多或少地根据需要工作。然后,当您verify.php再次访问时,您必须再次使用 URL 中的令牌,就像我在上面显示的那样,以便verify.php再次接受重新加载。

在第二次访问时,verify.php您可以在会话中重置令牌:

<?php

session_start();

unset($_SESSION['verifyToken']);

这意味着客户端无法verify.php再次访问,除非该index.php页面被使用。


推荐阅读