【问题标题】:Setting up a logout link properly正确设置注销链接
【发布时间】:2018-07-25 01:50:41
【问题描述】:

目前正在使用 PHP 开发一个小型注册/登录系统。情况如下:

我的第一个页面名为“signup.php”,用于注册和登录。提交表单后,您将被重定向到名为“diary.php”的第二个页面。单击提交按钮后,将在“用户”数据库中分别使用您的 ID 创建一个会话。如果没有 diary.php,则有一个注销链接。 如果您已注册或登录并且现在正在查看 diary.php,则除非您按注销,否则您无法查看 signup.php 页面。按下注销后,您将被重定向到 signup.php 页面,但 $_GET 数组中有一个注销变量。

<a href='signup.php?logout=1'>Logout</a>

我正在使用此注销变量来检查 $_GET 数组中是否存在“注销”键的那一刻,它会破坏会话并将我重定向回 signup.php 页面。

现在问题来了。假设我注册了一个新帐户,然后退出。一旦我注销,GET 中就会有一个“注销”键,对吧? (销毁会话)。如果我尝试注册另一个帐户,它实际上会注册我(在数据库上),但它会自动为我注销,因为我的链接中有注销密钥,而且还因为没有会话(我有在我的代码中,如果没有会话,几行代码会自动将您带回 signup.php)。

我希望这足以让大家清楚。我将把我的两页的代码留给你检查。谢谢!

  • 注册.php

    session_start();
    
     $conn = mysqli_connect("localhost","root","","diary");
    
    
     $error = '';
     $success = '';
    
    if (array_key_exists("submit",$_POST)) {
        if (!$_POST['email']) {
            $error.= "Email field is missing.<br>";
        }
    
        if (!$_POST["password"]) {
            $error .= "Password field is missing.<br>";
        }
    
        if ($error != '') {
            $error = "Fill in the missing field(s):<br>".$error;
        }
    
        else if ($_POST["submit"] == "Sign up") {
            $email = $_POST["email"];
            $query = "SELECT * FROM users WHERE email = '$email';";
            $result = mysqli_query($conn,$query);
            if (mysqli_num_rows($result) != 0) {
                $error .= "This account already exists!";
            } else {
                $email = $_POST["email"];
                $password = $_POST["password"];
                $query1 = "INSERT INTO users (email,password) VALUES ('$email','$password');";
                mysqli_query($conn,$query1);
                $success.= "Successfully signed up!";
                $query = "SELECT id FROM users WHERE email = '$email';";
                $row = mysqli_fetch_array(mysqli_query($conn,$query));
                $id=$row["id"];
                $_SESSION["id"] = $id;
                header("Location: diary.php");
    
                if (!isset($_POST["signUpRemember"])) {
                } else {
                    setcookie("id",$id,time() + 60*60*24*30);
                }            
            }
        }  else if ($_POST["submit"] == "Login")  {
    
            $email = $_POST["email"];
            $password = $_POST["password"];
            $query = "SELECT * FROM users WHERE email = '$email';";
            if (mysqli_num_rows(mysqli_query($conn,$query)) == 0) {
                $error.= "This account does not exist, sign up for a new account!";        
            } else {
                $query = "SELECT password FROM users WHERE email = '$email';";
                $rows = mysqli_fetch_array(mysqli_query($conn,$query));
                if ($password != $rows["password"]) {
                    $error.= "You have inserted the wrong password for this account. Please, try again!";
                } else {
                    $query = "SELECT id FROM users WHERE email = '$email';";
                    $rows = mysqli_fetch_array(mysqli_query($conn,$query)); 
                    $_SESSION["id"] = $rows["id"];
                    if (!isset($_POST["signUpRemember"])) {
                } else {
                    setcookie("id",$rows["id"],time() + 60*60*24*30);
                }    
                    header("Location :diary.php");
                }
    
            }
    
        }
    }
    
     if (array_key_exists("logout",$_GET)) {
    
         unset($_SESSION["id"]);
         setcookie("id","",time() - 60*600);
    
    
     } 
    
    if (array_key_exists("id",$_SESSION)) {
        header("Location: diary.php");
    
    }
    
    ?>
    

        <!-- Bootstrap CSS -->
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/css/bootstrap.min.css" integrity="sha384-Smlep5jCw/wG7hdkwQ/Z5nLIefveQRIY9nfy6xoR1uRYBtpZgI6339F5dgvm/e9B" crossorigin="anonymous">
        <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
        <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/js/bootstrap.min.js" integrity="sha384-o+RDsa0aLu++PJvFqy8fFScvbHFLtbvScb8AjopnFD+iEQ7wo/CG0xlczd+2O/em" crossorigin="anonymous"></script>
    
        <title>Secret Diary</title>
          <style>
    
              body {
                  margin:0;
                  height: 0;
              }
              #error {
                  background-color: red;
              }
              body {
                    background-image: url("img/bg.jpg");
                    background-color: #cccccc;
                }
    
              #containerLogin {
                    margin: auto;
                    width: 30%;
                    padding: 10px;
                    margin-top: 5%;
              }
    
              #containerSignup {
                    margin: auto;
                    width: 30%;
                    padding: 10px;
                    margin-top: 5%;
    
              }
    
    
              .switchBtt {
                  margin-top: 5%;
                  width: 70%;
              }
    
              .display-4 {
                  font-weight: 300;
              }
    
    
    
          </style>
      </head>
      <body>
    
          <div id="error"><?php if ($error != "") { echo $error; } else { echo "<script>$( '#error' ).css('background-color', 'green');</script>"; echo $success;} ?></div>
          <div id="containerLogin">
           <center><h1 class="display-4 text-muted "><font color="#6D3E6C">Secret Diary</font></h1>
               <br>
                     <h5 class=" text-muted "><font color="#DFD2CA">Welcome back!</font></h5>
               <br>
         <form method="post" name="signup">
      <div class="form-group">
    
    
        <label for="email">Email address</label>
        <input type="email" class="form-control" name="email" aria-describedby="emailHelp" placeholder="Enter email">
        <small id="emailHelp" class="form-text text-muted">We'll never share your email with anyone else.</small>
      </div>
      <div class="form-group">
        <label for="password">Password</label>
        <input type="password" class="form-control" name="password" placeholder="Password">
      </div>
      <div class="form-group form-check ">
        <input type="checkbox" class="form-check-input" value="checked" name="signUpRemember">
        <label class="form-check-label" for="signUpRemember">Keep me signed in</label>
      </div>
      <input class="btn btn-primary" type="submit" value="Login" name="submit">
     </form>
               <div  class="btn btn-secondary switchBtt">Switch to sign-up panel &#x21B9; </div>
    
        </center>
    
          </div>
                <div id="containerSignup">
           <center><h1 class="display-4 text-muted "><font color="#6D3E6C">Secret Diary</font></h1>
               <br>
                     <h5 class="text-muted "><font color="#DFD2CA">Sign up today, for free!</font></h5>
               <br>
         <form method="post" name="signup">
      <div class="form-group">
        <label for="email">Email address</label>
        <input type="email" class="form-control" name="email" aria-describedby="emailHelp" placeholder="Enter email">
        <small id="emailHelp" class="form-text text-muted">We'll never share your email with anyone else.</small>
      </div>
      <div class="form-group">
        <label for="password">Password</label>
        <input type="password" class="form-control" name="password" placeholder="Password">
      </div>
      <div class="form-group form-check ">s
        <input type="checkbox" class="form-check-input" value="checked "name="LoginRemember">
        <label class="form-check-label" for="LoginRemember">Keep me signed in</label>
      </div>
      <input class="btn btn-primary" type="submit" value="Sign up" name="submit">
     </form>
               <div class="btn btn-secondary switchBtt">Switch to login panel &#x21B9; </div>
    
        </center>
          </div>
    
        <!-- Optional JavaScript -->
        <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    
      </body>
        <script>
            $("#containerLogin").hide();
            $(".switchBtt").click (function () {
              $("#containerLogin").toggle();
              $("#containerSignup").toggle();
            });
        </script>
    </html>
    
    • 日记.php

    session_start();
    
        if (array_key_exists("id",$_SESSION)) {
            echo "<p>Logged In! <a href='signup.php?logout=1'>Logout</a></p>";
            echo "<br>";
            echo $_SESSION["id"]."<br>";
        } else {
            header("Location: signup.php");
        }
    
        ?>
    

【问题讨论】:

  • 长问题,很多没用的html,但没有明确的问题。你有编程问题还是概念问题?

标签: php logout


【解决方案1】:

出于这个确切原因,您通常不应该使用 GET 查询字符串来更改应用程序中的状态。

GET requests are not supposed to have any side effects 和浏览器将尝试利用这一点来加速页面加载,方法是在用户点击页面之前预先请求页面,或者缓存页面而不实际从服务器请求它。这些情况中的任何一种都会导致意外行为。此外,如果有人用 ?logout=1 为页面添加书签,他们将(可能不小心)在返回该页面时将自己注销。

最好使用 POST 动词。您可以轻松地使用 HTML

标记和提交按钮:
<form action="signup.php" method="POST" id="logout_form">
    <input type="hidden" name="logout" value="1" />
    <input type="submit" value="Logout" />
</form>

在您的 PHP 中,您可以通过执行以下操作来检测是否有人点击了按钮:

if(isset($_POST['logout'])) {
    //log user out
}

【讨论】:

  • 你的想法效果更好。我决定删除 signup.php 中的代码,该代码在 GET 数组中有注销键时将用户注销,并移至注销按钮所在的 diary.php。现在由于某种原因,当我单击注销按钮时,我没有被重定向回注册页面。这是 diary.php (ghostbin.com/paste/dkn2r) 的新代码
  • 假设你还没有写出任何东西,你总是可以在处理后使用 Header("Location: signup.php"); 重定向用户。需要注意的是,在将任何内容写入客户端之前,您必须这样做。
  • 我在 signup.php 中有一些代码可以检查是否有会话。如果有,它会自动将您重定向到 diary.php。我删除了那段代码并尝试单击按钮,它确实有效。这现在告诉我,当我单击按钮时,它实际上并没有取消设置会话,因为某种原因会强制 signup.php 页面中的代码立即将您重定向回 diary.php(顺便说一句,我编辑了我以前的评论,看看。它有diary.php代码)
  • 没关系,是表单中的“action”属性导致了问题!出于某种原因,它只是阻止会话取消设置。你甚至不能让它与“标题”功能齐头并进。我不得不删除它并保留标题功能以便它工作。还是谢谢你:) 非常感谢。
【解决方案2】:

Michael 的回答很好(并且被接受了!),但目前我工作的地方正在通过可访问性审核,所以我有这个想法。屏幕阅读器、使用高对比度自定义样式表的人等无法像处理纯文本那样轻松处理表单按钮。

我在使用session_destroy 的(旧)PHP 清除会话中也遇到了问题,所以我遍历会话变量和unset 它们。

<a href="/logout.php">Log out</a>

然后logout.php:

<?php

session_start();

foreach($_SESSION as $sk=>$sv){
  unset($_SESSION[$sk]);
}

header("location: /");

?>

【讨论】:

  • 请问,将注销代码单独放在另一个页面,然后在代码执行后重定向到主页有什么好处?为什么不在存在注销按钮/链接的页面中运行注销代码?
猜你喜欢
  • 2014-01-16
  • 1970-01-01
  • 2017-03-19
  • 1970-01-01
  • 2015-02-06
  • 1970-01-01
  • 2019-01-19
  • 1970-01-01
  • 2018-08-03
相关资源
最近更新 更多