环境
场景一CSRF-token保护
php
<?php
session_start();
// 如果是AJAX请求获取token
if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest' && $_SERVER['REQUEST_METHOD'] === 'GET') {
// 每次AJAX GET请求都生成新的CSRF令牌
$_SESSION['csrf_token'] = md5(uniqid(mt_rand(), true));
header('Content-Type: application/json');
echo json_encode(['csrf_token' => $_SESSION['csrf_token']]);
exit;
}
// 验证CSRF令牌 (从请求头获取)
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$csrf_token_header = isset($_SERVER['HTTP_X_CSRF_TOKEN']) ? $_SERVER['HTTP_X_CSRF_TOKEN'] : null;
if (!isset($csrf_token_header) || $csrf_token_header !== $_SESSION['csrf_token']) {
header('Content-Type: application/json');
echo json_encode(['error' => 'CSRF令牌验证失败!']);
exit;
}
// CSRF令牌验证成功,销毁会话中的令牌,实现一次一密
unset($_SESSION['csrf_token']);
// 处理登录逻辑
$username = $_POST["username"];
$password = $_POST["password"];
if ($username === "admin" && $password === "passwd") {
echo json_encode(['success' => true, 'message' => '登录成功!']);
} else {
echo json_encode(['success' => false, 'message' => '用户名或密码错误!']);
}
exit;
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登录系统</title>
<style>
body {
font-family: Arial, sans-serif;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background-color: #f0f2f5;
}
.login-container {
background-color: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
width: 300px;
}
.form-group {
margin-bottom: 15px;
}
label {
display: block;
margin-bottom: 5px;
}
input[type="text"], input[type="password"] {
width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
box-sizing: border-box;
}
button {
width: 100%;
padding: 10px;
background-color: #1677ff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background-color: #4096ff;
}
.error-message {
color: red;
margin-top: 10px;
text-align: center;
}
.success-message {
color: green;
margin-top: 10px;
text-align: center;
}
</style>
</head>
<body>
<div class="login-container">
<h2 style="text-align: center;">用户登录</h2>
<form id="loginForm" method="POST" action="login.php">
<div class="form-group">
<label for="username">用户名:</label>
<input type="text" id="username" name="username" required>
</div>
<div class="form-group">
<label for="password">密码:</label>
<input type="password" id="password" name="password" required>
</div>
<button type="submit">登录</button>
<div id="message"></div>
</form>
</div>
<script>
document.getElementById('loginForm').addEventListener('submit', function(e) {
e.preventDefault();
// 先获取CSRF令牌
fetch('login.php', {
method: 'GET',
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
})
.then(response => response.json())
.then(data => {
const csrfToken = data.csrf_token;
// 获取表单数据
const formData = new FormData(this);
// 发送登录请求,将CSRF令牌放入HTTP头
fetch('login.php', {
method: 'POST',
headers: {
'X-CSRF-Token': csrfToken,
'X-Requested-With': 'XMLHttpRequest' // 添加此头部,后端用于区分是否为AJAX请求
},
body: formData
})
.then(response => response.json())
.then(data => {
if (data.error) {
document.getElementById('message').innerHTML = `<div class="error-message">${data.error}</div>`;
} else if (data.success) {
document.getElementById('message').innerHTML = `<div class="success-message">${data.message}</div>`;
} else {
document.getElementById('message').innerHTML = `<div class="error-message">${data.message}</div>`;
}
})
.catch(error => {
console.error('Error:', error);
document.getElementById('message').innerHTML = '<div class="error-message">登录请求失败</div>';
});
})
.catch(error => {
console.error('Error:', error);
document.getElementById('message').innerHTML = '<div class="error-message">获取CSRF令牌失败</div>';
});
});
</script>
</body>
</html>
plain
beforeRequest = func(req) {
pkg = `
GET /csrf/login.php HTTP/1.1
Host: 192.168.2.10
sec-ch-ua-platform: "Windows"
Sec-Fetch-Dest: empty
sec-ch-ua-mobile: ?0
Accept-Encoding: gzip, deflate, br, zstd
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36
Cookie: PHPSESSID=d5rv1ovh8cff449mf6hd0ntpa5
X-Requested-With: XMLHttpRequest
sec-ch-ua: "Google Chrome";v="137", "Chromium";v="137", "Not/A)Brand";v="24"
Sec-Fetch-Site: same-origin
Accept: */*
Sec-Fetch-Mode: cors
Accept-Language: zh-CN,zh;q=0.9
`
// req,rsp,_=poc.HTTP(pkg, poc.gmTls(),poc.https(true))//开启国密,开启https
req2,_,_=poc.HTTP(pkg)
a,_=poc.ParseBytesToHTTPResponse(req2)//获取响应体
json_token,_ = io.ReadAll(a.Body) //{"csrf_token":"3fe1d20bcd8a4c11154b1d91e7f0115a"}
token= json.loads(json_token)//解析获取csrf_token对应的内容
csrf_token = token["csrf_token"]
req = poc.ReplaceHTTPPacketHeader(req, "X-CSRF-Token", csrf_token)//替换数据包头中的X-CSRF-Token对应的内容
return req
}
可以发现使用热加载写完代码,会自动修改"X-CSRF-Token",相对比较方便