Open Lichen5221 opened 3 years ago
SESSION 的使用,在每個有使用 SESSION 的檔案中,第一行都要加上 session_start(); 確保 SESSION 開啟。
index.php
<?php
session_start();
require_once("conn.php");
require_once("utils.php");
$username = NULL;
if(!empty($_SESSION['username'])) {
$username = $_SESSION['username'];
}
$result = $conn -> query("SELECT * FROM comments order by id desc");
if(!$result) {
die('Error:' . $conn -> error);
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>留言板</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header class="warning">
<strong> 警告!有資安漏洞! </strong>
</header>
<main class="board">
<div>
<?php if (!$username) { ?>
<a class="board__btn" href="register.php">註冊</a>
<a class="board__btn" href="login.php">登入</a>
<?php } else { ?>
<a class="board__btn" href="logout.php">登出</a>
<h3>歡迎!<?php echo $username; ?></h3>
<?php } ?>
</div>
<h1 class="board__title">Comments</h1>
<?php
if(!empty($_GET['errCode'])) {
$code = $_GET['errCode'];
$msg = 'Error';
if ($code === '1') {
$msg = '錯誤:資料不齊全';
}
echo '<h2 class="error">' . $msg . '</h2>';
}
?>
<?php if ($username) { ?>
<form class="board__new-comment-form"method="POST" action="handle_add_comment.php">
<textarea name="content" rows="5"></textarea>
<input class="board__submit-btn"type="submit" />
</form>
<?php } else { ?>
<h3>請登入發布留言</h3>
<?php } ?>
<div class="board__hr"></div>
<section>
<?php
while($row = $result -> fetch_assoc()) {
?>
<div class="card">
<div class="card__avatar">
</div>
<div class="card__body">
<div class="card__info">
<span class="card__author">
<?php echo $row['nickname'];?>
</span>
<span class="card__time">
<?php echo $row['created_at'];?>
</span>
</div>
<p class="card__content"><?php echo $row['content']?></p>
</div>
</div>
<?php } ?>
</section>
</main>
</body>
</html>
handle_login.php
<?php
session_start();
require_once('conn.php');
require_once('utils.php');
if (
empty($_POST['username']) ||
empty($_POST['password'])
) {
header('Location: login.php?errCode=1');
die('資料不齊全');
}
$username = $_POST['username'];
$password = $_POST['password'];
$sql = sprintf(
"select * from users where username='%s' and password='%s'",
$username,
$password
);
$result = $conn->query($sql);
if (!$result) {
die($conn->error);
}
if ($result->num_rows) {
$_SESSION['username'] = $username;
header("Location: index.php");
} else {
header("Location: login.php?errCode=2");
}
?>
logout.php
<?php
session_start();
session_destroy();
header("Location: index.php");
?>
utils.php
<?php
require_once("conn.php");
function randomToken() {
$s = '';
for ($i = 1; $i <= 16; $i++) {
$s .= chr(rand(65, 90));
}
return $s;
}
function getUserFromUsername($username) {
global $conn;
$sql = sprintf(
"select * from users where username = '%s'",
$username
);
$result = $conn -> query($sql);
$row = $result -> fetch_assoc();
return $row;
}
?>
handle_add_comment.php
<?php
session_start();
require_once('conn.php');
require_once('utils.php');
if (
empty($_POST['content'])
) {
header('Location: index.php?errCode=1');
die('資料不齊全');
}
$user = getUserFromUsername($_SESSION['username']);
$nickname = $user['nickname'];
$content = $_POST['content'];
$sql = sprintf(
"insert into comments(nickname, content) values('%s', '%s')",
$nickname,
$content
);
$result = $conn->query($sql);
if (!$result) {
die($conn->error);
}
header("Location: index.php");
?>
老師真是用心良苦,為了要讓我們知道 Cookie 跟 SESSION 背後的機制,特地弄了上面那一次,的確是有比較懂了,感謝老師。
這件事第一次聽說,非常酷。
原來資料庫不能直接傳密碼給我的原因,是因為他也不知道我的密碼!
所以可以直接傳密碼給我的網站是有漏洞可鑽囉?
只要給你密碼的網站都有資安風險!(亂下結論)
這部分我想要明天再看了。
修正偽造身份問題:給予通行證
index.php
utils.php (大家都能用的程式包起來)
handle_login.php
logout.php
handle_add_comment.php
建立 token 的資料庫,從 token 拿到 username ,再去對應 nickname。
有了隨機 token 後,就無法猜到其他帳號的 token ,也就無法偽造身份。