正确设置注销 link
Setting up a logout link properly
目前正在使用 Sign-Up/Login 系统与 PHP 一起工作。情况是这样的:
我的第一页名为 "signup.php",用于注册和登录。提交表单后,您将被重定向到名为 "diary.php" 的第二页。单击提交按钮后,将在 "users" 数据库中分别使用您的 ID 创建一个会话。如果没有 diary.php,则会出现注销 link。
如果您已注册或登录并且现在正在查看 diary.php,您将无法查看 signup.php 页面,除非您按下注销。一旦您按下注销,您将被重定向到 signup.php 页面,但在 $_GET 数组中有一个注销变量。
<a href='signup.php?logout=1'>Logout</a>
我正在使用这个注销变量来检查 $_GET 数组中是否存在 "logout" 键,它会破坏会话并将我重定向回 signup.php 页面。
问题来了。假设我注册了一个新帐户,然后注销了。一旦我注销,GET 中就会有一个 "logout" 键,对吧? (销毁会话)。如果我尝试注册另一个帐户,它实际上会为我注册(在数据库上),但它会自动为我注销,因为我的 link 中有注销密钥,也因为没有会话(如果没有会话,我的代码中有几行会自动将您带回 signup.php)。
我希望这足以让大家明白。我将留下我的两个页面的代码供您检查。谢谢!
signup.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 ↹ </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 ↹ </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>
- diary.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");
}
?>
出于这个原因,您通常不应该使用 GET 查询字符串来更改应用程序中的状态。
GET requests are not supposed to have any side effects 并且浏览器将尝试利用这一点来加快页面加载速度,方法是在用户单击页面之前预先请求页面,或者通过缓存页面而不实际从服务器请求它。这些情况中的任何一种都会导致意外行为。此外,如果有人在页面上添加了 ?logout=1 书签,他们会(可能不小心)在 return 访问该页面时随时注销。
最好用POST这个动词。您可以轻松地使用 HTML
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: /");
?>
目前正在使用 Sign-Up/Login 系统与 PHP 一起工作。情况是这样的:
我的第一页名为 "signup.php",用于注册和登录。提交表单后,您将被重定向到名为 "diary.php" 的第二页。单击提交按钮后,将在 "users" 数据库中分别使用您的 ID 创建一个会话。如果没有 diary.php,则会出现注销 link。 如果您已注册或登录并且现在正在查看 diary.php,您将无法查看 signup.php 页面,除非您按下注销。一旦您按下注销,您将被重定向到 signup.php 页面,但在 $_GET 数组中有一个注销变量。
<a href='signup.php?logout=1'>Logout</a>
我正在使用这个注销变量来检查 $_GET 数组中是否存在 "logout" 键,它会破坏会话并将我重定向回 signup.php 页面。
问题来了。假设我注册了一个新帐户,然后注销了。一旦我注销,GET 中就会有一个 "logout" 键,对吧? (销毁会话)。如果我尝试注册另一个帐户,它实际上会为我注册(在数据库上),但它会自动为我注销,因为我的 link 中有注销密钥,也因为没有会话(如果没有会话,我的代码中有几行会自动将您带回 signup.php)。
我希望这足以让大家明白。我将留下我的两个页面的代码供您检查。谢谢!
signup.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 ↹ </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 ↹ </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>
- diary.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"); } ?>
出于这个原因,您通常不应该使用 GET 查询字符串来更改应用程序中的状态。
GET requests are not supposed to have any side effects 并且浏览器将尝试利用这一点来加快页面加载速度,方法是在用户单击页面之前预先请求页面,或者通过缓存页面而不实际从服务器请求它。这些情况中的任何一种都会导致意外行为。此外,如果有人在页面上添加了 ?logout=1 书签,他们会(可能不小心)在 return 访问该页面时随时注销。
最好用POST这个动词。您可以轻松地使用 HTML
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: /");
?>