target 指向頁面中一個隱藏的 <iframe><!DOCTYPE html>
<html lang="zh-Hant">
<head>
<meta charset="UTF-8">
<title>無刷新登錄演示</title>
<style>
#login-form { max-width: 300px; margin: 50px auto; padding: 20px; border: 1px solid #ddd; }
.form-group { margin-bottom: 15px; }
label { display: block; margin-bottom: 5px; }
input[type="text"], input[type="password"] { width: 100%; padding: 8px; box-sizing: border-box; }
button { width: 100%; padding: 10px; background: #007bff; color: white; border: none; cursor: pointer; }
#message { margin-top: 15px; color: #28a745; font-weight: bold; }
iframe { display: none; }
</style>
</head>
<body>
<div id="login-area">
<form action="login.php" method="post" target="hidden-frame" id="login-form">
<div class="form-group">
<label>用戶名</label>
<input type="text" name="username" id="username" required>
</div>
<div class="form-group">
<label>密碼</label>
<input type="password" name="password" id="password" required>
</div>
<button type="submit">登錄</button>
</form>
<div id="message"></div>
</div>
<!-- 隱藏 iframe 接收登錄響應 -->
<iframe name="hidden-frame" id="hidden-frame"></iframe>
<script>
// 可選:表單提交時顯示加載狀態
document.getElementById('login-form').addEventListener('submit', function() {
document.getElementById('message').textContent = '正在登錄...';
document.getElementById('message').style.color = '#6c757d';
});
</script>
</body>
</html>
<?php
// 模擬用戶驗證(實際項目連接數據庫、驗證密碼哈希)
$users = [
'admin' => '$2y$10$...', // password_hash('123456', PASSWORD_DEFAULT)
'demo' => '$2y$10$...'
];
$username = $_POST['username'] ?? '';
$password = $_POST['password'] ?? '';
$success = false;
$message = '用戶名或密碼錯誤';
if (isset($users[$username]) && password_verify($password, $users[$username])) {
// 登錄成功:設置 Session
session_start();
$_SESSION['user_id'] = $username;
$_SESSION['login_time'] = time();
$success = true;
$message = '登錄成功!歡迎回來,' . htmlspecialchars($username);
}
// 輸出 JavaScript 操作父頁面
header('Content-Type: text/html; charset=UTF-8');
?>
<script>
// 通知父頁面登錄結果
var msgEl = parent.document.getElementById('message');
var loginArea = parent.document.getElementById('login-area');
if (= $success ? 'true' : 'false' ?>) {
msgEl.textContent = '= addslashes($message) ?>';
msgEl.style.color = '#28a745';
// 隱藏登錄表單,顯示用戶信息
loginArea.innerHTML = '<div class="user-info">' +
'<span>= addslashes($username) ?></span> ' +
'<a href="logout.php">退出登錄</a>' +
'</div>';
} else {
msgEl.textContent = '= addslashes($message) ?>';
msgEl.style.color = '#dc3545';
}
</script>
iframe 方案屬於早期技術,現代項目推薦使用 AJAX:
<!-- 表單改為不提交,綁定 JS 事件 -->
<form id="login-form">...</form>
<script>
document.getElementById('login-form').addEventListener('submit', async (e) => {
e.preventDefault();
const formData = new FormData(e.target);
const res = await fetch('login_api.php', {
method: 'POST',
body: formData,
credentials: 'include' // 攜帶 Cookie
});
const data = await res.json();
const msgEl = document.getElementById('message');
if (data.success) {
msgEl.textContent = data.message;
msgEl.style.color = '#28a745';
// 更新頁面 UI
document.getElementById('login-area').innerHTML = `...`;
} else {
msgEl.textContent = data.message;
msgEl.style.color = '#dc3545';
}
});
</script>
password_hash() / password_verify()。csrf_token,服務端驗證。HttpOnly、Secure、SameSite Cookie 標誌。