登录后重定向到之前的页面?

62

成功登录后,用户应该被重定向到他来自的页面,比如说他正在浏览一篇文章并想要登录以便留下评论,那么他应该被重定向到他正在浏览的文章。以下是我的建议:

login.php 显示登录表单:

<form method="post" action="login-check.php">
... //input for username and password
</form>

login-check.php文件用于检查用户名和密码是否已输入,用户是否存在以及是否已登录,如果向login.php发送了一个p参数,则会进行检查:

<?php
session_start();
if((empty($username) OR empty($password) AND !isset($_SESSION['id_login']))) {
   header("Location:login.php?p=1");
   exit();
}
elseif (!user_exists($username,$password) AND !isset($_SESSION['id_login'])) {
   header("Location:login.php?p=2");
   exit();
}
elseif(isset($_SESSION['id_login'])) {
   header("Location:login.php?p=3");
   exit();
}
?>

然后参数p被发送回login.php并显示相应的消息:

<?php
if(isset($_GET['p'])) {
  $p = $_GET["p"];

  if($p=="1")
    echo "<p class=\"red\">You didn't fill the form.</p><br></br>";
  if($p=="2")
    echo "<p class=\"red\">User exists.</p><br></br>";
  if($p=="3")
    header("Location: index.php");
}
?>

但是,在成功登录后,应该跳转到用户之前所在的页面,而不是跳转到index.php。我尝试了不同的方法,但要么根本不起作用,要么返回到login.php。


您应该将要重定向用户返回的页面作为查询参数传递到登录页面。 - Anirudh Ramanathan
18个回答

82

一种常见的方法是通过$_GET变量将用户当前页面传递给登录表单。

例如:如果您正在阅读文章,并且想要留下评论。 评论的URL为comment.php?articleid=17。 当comment.php正在加载时,它注意到您未登录。 它想要将您发送到login.php,就像您之前展示的那样。 然而,我们将更改您的脚本,以便还告诉登录页面记住您的位置:

header("Location:login.php?location=" . urlencode($_SERVER['REQUEST_URI']));
// Note: $_SERVER['REQUEST_URI'] is your current page

这将把用户发送到:login.php?location=comment.php%3Farticleid%3D17。现在,login.php 应检查是否填充了 $_GET['location']。如果已填充,则将用户发送到此位置(在本例中为 comment.php?articleid=17)。例如:

//  login.php
echo '<input type="hidden" name="location" value="';
if(isset($_GET['location'])) {
    echo htmlspecialchars($_GET['location']);
}
echo '" />';
//  Will show something like this:
//  <input type="hidden" name="location" value="comment.php?articleid=17" />

 

//  login-check.php
session_start();

//  our url is now stored as $_POST['location'] (posted from login.php). If it's blank, let's ignore it. Otherwise, let's do something with it.
$redirect = NULL;
if($_POST['location'] != '') {
    $redirect = $_POST['location'];
}

if((empty($username) OR empty($password) AND !isset($_SESSION['id_login']))) {
    $url = 'login.php?p=1';
    // if we have a redirect URL, pass it back to login.php so we don't forget it
    if(isset($redirect)) {
        $url .= '&location=' . urlencode($redirect);
    }
   header("Location: " . $url);
   exit();
}
elseif (!user_exists($username,$password) AND !isset($_SESSION['id_login'])) {
    $url = 'login.php?p=2';
    if(isset($redirect)) {
        $url .= '&location=' . urlencode($redirect);
    }
   header("Location:" . $url);
   exit();
}
elseif(isset($_SESSION['id_login'])) {
    // if login is successful and there is a redirect address, send the user directly there
    if($redirect) {
        header("Location:". $redirect);
    } else {
        header("Location:login.php?p=3");
    }
    exit();
}

需要注意的事项

在将用户重定向到某个URL之前,应对$_GET['location']进行一些验证。例如,如果我告诉使用您网站的人点击此链接:login.php?location=http%3A%2F%2Fmalice.com%2Fevilpage.php... 那么他们将被发送到一个外部URL,该URL会尝试执行一些恶意操作。

始终确保在传递URL作为$_GET参数时使用urlencode。这将对特殊的URL字符(如?&%)进行编码,以防止它们破坏您的URL(例如:login.php?location=comment.php?id=17 <- 这里有两个?,将无法正常工作)


1
@AlejandraUzelac,例如,如果您要注销并查看此问题并尝试编写答案,则会在页面底部看到“登录”链接。 此链接指向此处:http://stackoverflow.com/users/login?returnurl=%2fquestions%2f14523468%2fredirecting-to-previous-page-after-login-php 您将看到此问题的URL包含在登录URL中。 - Chris
不过还有一件事...如果用户想要在categories.php页面登录怎么办?因为那里没有表单和输入按钮。 - Alejandra Uzelac
让我们在聊天中继续这个讨论:http://chat.stackoverflow.com/rooms/23381/discussion-between-chris-and-alejandra-uzelac - Chris
先生,我不理解在login.php中的htmlspecialchars($_GET['location'])的用法。因为它将特殊字符如&,"等转换为HTML实体,但是URL中的文件名不包含这些字符。在这种情况下使用htmlspecialchars函数是否没有效果? - Parveez Ahmed
1
嗨@rosemary,这是一项安全措施,旨在防止所谓的XSS。想象一下,我在Reddit上发布了一个指向Alejandra网站的链接:http://example.com/login.php?location=" onload="window.location('malice.com/spyware')。当您访问此页面时,input看起来像这样:<input type="hidden" name="location" value="example.com/login.php?location=" onload="window.location('malice.com/badwebpage')"。这个HTML将用户发送到了malice.com!使用htmlspecialchars有助于防止发生这种情况。在呈现用户提供的输入时使用htmlspecialchars是最佳实践。 - Chris
非常好的答案,解释得非常清楚。也为我节省了很多时间。但是提供的代码中有一个错误,在最后一部分的 if($redirect)) 中有一个多余的括号。 - Galzor

11

当用户到达登录页面时,请使用此选项查看其来源

$_SERVER['HTTP_REFERER']

接着将这个值设置到会话中,在他通过验证后使用会话中的URL将其重定向回来。但在此之前,您应该进行一些检查,看看URL是否属于您的站点。也许他是直接从另一个站点登录的 :)


3
这个值是完全不可靠的,例如用户安装了一个浏览器插件来禁止发送referer。 - Andreas
这是使用HTTP的标准方法,如果有任何阻止从客户端请求中读取该值的问题,那就是客户端的问题。 - Pablo Pazos

11

您可以使用php保存页面,如下所示:

$_SESSION['current_page'] = $_SERVER['REQUEST_URI']

并返回具有以下内容的页面:

header("Location: ". $_SESSION['current_page'])

3

另一种方法,使用SESSION

将当前URL分配给会话(在每个页面上使用)

$_SESSION['rdrurl'] = $_SERVER['REQUEST_URI'];

在您的登录页面中,请使用以下内容:
if(isset($_SESSION['rdrurl']))
header('location: '.$_SESSION['rdrurl']);
else
header('location: http://example.com');

3

你可能需要将重定向的 URL 放在一个 POST 变量中。


3

鉴于登录页面是一个独立的页面,我假设你想要重定向到用户从哪里访问登录页面的页面。

$_SERVER['REQUEST_URI'] 只会保留当前页面。你需要使用 $_SERVER['HTTP_REFERER']

因此,在你的表单中将 HTTP_REFERER 保存在隐藏元素中 <input type="hidden" name="referer" value="<?= $_SERVER['HTTP_REFERER'] ?>" />,但请记住,在处理该表单的 PHP 中,你需要一些逻辑来在登录失败时重定向回登录页面,但也要检查 referer 是否实际上是你的网站,如果不是,则重定向回首页。


2

使用类似以下的内容:

$_SERVER['HTTP_REFERER'];

如果登录成功,显示一个链接,上面写着“点击此处返回”,还有一个链接指向来路页面。当页面加载时,使用一些JavaScript代码自动加载该页面(不要使用back()或其他函数,因为它不会重新加载页面,这会导致用户似乎从未登录)。

2

您可以使用会话(session)来存储您希望在登录后返回的当前页面,并且如果正确维护会话,那么这对其他页面也有效。这是一种非常有用的技术,因为您可以使用它来开发面包屑导航。


2

你可以使用以下内容:

$refererpage = $_SERVER['HTTP_REFERER']; //get referer stored in a variable
if (strpos($refererpage, $_SERVER['SERVER_NAME']) == TRUE) { //if the start position of the referer and the server name is equal
    $refvar= $refererpage; //create a mew variable to be used to locate header
} else { //if referer's address is not the same as server name
    $refvar= "index.php"; //set the variable to another direction for this request
}

并且可以在任何您想要的位置添加标题,如下所示:

header('location: '. $refvr); //set the header location to the referer varaible

1

在登录页面中,您应该首先使用 $_SERVER['HTTP_REFERER'] 将用户引荐页面存储到变量中。

例如:

<?php 
    session_start();
    $refPage = $_SERVER['HTTP_REFERER']; 
?>

现在当用户点击登录时,将标题位置更改为用户引用页面

例如:

<?php 
if(isset($_POST[login])){
    session_start();
    header('location:' . $refPage);
}
?>

在这段时间里,您应该首先检查用户是否引用了空页面,因为您的用户可能会直接访问您的登录页面,那么您的$refPage变量将为空,所以在点击登录后,页面会停留在此处。
例如:
<?php
if(isset($_POST[login])){
    session_start();
    $refPage = $_SERVER['HTTP_REFERER'];  // get reffer page url
    if(empty($refPage)){ 
        header('location: yourredirectpage'); // if ref page is empty then set default redirect page.
    }else{
        header('location:' . $refPage); // or if ref page in not empty then redirect page to reffer page
    }
}
?>


你可以使用input type hidden,其中你可以设置value为$_SERVER['HTTP_REFERER']。
例如:
<input type="hidden" name="refPage" value="<?php echo $_SERVER['HTTP_REFERER']; ?>">

当用户点击登录时,您可以获取refPage的值并重定向到先前的页面。您还应检查空引用页面。因为您的用户可能会直接访问您的登录页面。
谢谢。

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