如何在php中正确使用 $_SERVER['HTTP_REFERER']?

6
假设我有两个页面page1.phppage2.php,我希望只有当从page1.php重定向到page2.php时才显示page2.php,并且我在page2.php中插入了以下代码。
if($_SERVER['HTTP_REFERER'] == "page1.php")
{
    //keep displaying page2.php
}else{
    //if it is not redirected from page1.php
    header('Location:page1.php')
    //redirect the user back to page1.php 
}

这段代码很好用,直到我在page2.php上添加了一个表单和提交按钮后出现了问题。当点击提交按钮时,页面会刷新,这意味着HTTP_REFERER将更改为page2.php,因此我的if语句失败了,它会把我带回page1.php,但我不希望发生这种情况。有没有什么方法可以防止这种情况的发生?
提前感谢。

Referer是用户提供的值,不能依赖它,因为它可能被篡改或省略。相反,应该使用会话,设置一个会话变量在page1.php上,并在page2.php上进行检查。 - Charlotte Dunois
@CharlesAddis,我添加了代码,但似乎没有任何变化。 - surafel
4个回答

16

我不建议使用HTTP_REFERER

  1. 它在浏览器中很容易被篡改。

  2. 一些用户的浏览器可能有安全设置,根本不发送此标头。

  3. 它在HTTPS下不可访问。

  4. 一些代理会从请求中剥离此标头。

  5. 添加 - 查看此问题的答案


正如 Charlotte Dunois 在评论中所述,在发送表单之前最好设置会话值,然后在 page2 上检查它。

page1.php:

$_SESSION[ 'display_page2' ] = TRUE;
//rest of the content

page2.php:

if ( (isset( $_SESSION[ 'display_page2' ] ) && $_SESSION[ 'display_page2' ] === TRUE ) || isset( $_POST[ 'some_form_input' ] ) ) {
  //keep displaying page2.php
} else {
  header('Location:page1.php');
  exit;
}

通过使用 isset( $_POST[ 'some_form_input' ] ),您可以检查表单是否已通过 POST 方法发送。

必要时,您可以使用unset( $_SESSION[ 'display_page2' ] ); 或将其设置为不同的值来取消会话。


添加或运算符并不能解决问题,它会允许用户通过使用URL访问page2.php页面。 - surafel
1
引用者仍然可以通过HTTPS访问。 - Charlotte Dunois
来到这篇文章已经过去几年了,但我只是想展示第一个条件可以通过使用empty方法来简化,该方法检查isset和TRUE的值:if (!empty($_SESSION['display_page2']) - pti_jul
@pti_jul 是的,它可以。只要注意有些代码检查工具不允许使用 empty() 因为它含糊不清。 - Petr Hejda
@PetrHejda 好的,谢谢,我没有考虑到那个。 - pti_jul

4

我建议不要使用$_SERVER['HTTP_REFERER'],因为它很容易被伪造。

相反,您可以使用setcookie("page1", 1);在输出任何标记之前,在加载页面1时设置一个cookie。然后在页面2上检查它。

if(isset($_COOKIE['page1']))
{
    //keep displaying page2.php
}else{
    //if it is not redirected from page1.php
    header('Location:page1.php')
    //redirect the user back to page1.php 
}

如果不指定到期日期,那么Cookie将在浏览器关闭时过期。在这种情况下,使用Cookie还可以使代码更易于他人阅读。


这正是我建议的方法,Surafel。使用 cookies 会得到更好的结果,并且可以用于许多不同的方式!请查看 http://www.w3schools.com/php/func_http_setcookie.asp 获取一个基本示例。 - Jarod Thornton
@jarmerson,请将setcookie的php.net文档页面链接提供给我们,而不是w3fools - Charlotte Dunois
1
@Cha 我已经有了,他只是在帮助其他人找另一个例子。官方的并不总是那么有用。 - Roshan Bhumbra

2
<?php
if(($_SERVER['HTTP_REFERER'] == "page1.php") || (isset($_POST['submit']) && $_SERVER['HTTP_REFERER']=="page2.php"))
{
    //keep displaying page2.php
}else{
    //if it is not redirected from page1.php
    header('Location:page1.php');
    //redirect the user back to page1.php 
}

?>

如果引荐来源不是第一页,您可以检查以下条件:如果引荐来源为页面2且已提交帖子,则检查;或者检查引荐来源是否为页面1或已提交帖子。这是避免您问题的一种可能性。

0
<?php

/* 
    this page allows links from the following pages

    public.php?id=links
    private.php?id=links

don't allow if visitors come from anywhere else

this example would only work if I used the entire URL in the 'if' statement 
*/

$referringpage = $_SERVER['HTTP_REFERER'];

if ( $referringpage == "http://www.example.com/public.php?id=links" ) {
$pass = "yes";
} elseif ( $referringpage == "http://www.example.com/private.php?id=links" ) {
$pass = "yes";
} else {
$pass = "no";
}


if ( $pass == "yes" ) {
// do the function this page was made to do
} 

header( "Location: http://www.example.com/public.php?id=links" );

?>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接