所以我有一个带有 4 个简单按钮的 SPA。该网站实际上只是我的数字简历。我在顶部有两个按钮: 打开一个下载模式窗口,其中包含验证码。他们完成验证码,下载按钮被启用,它应该使用下载处理程序 php 脚本下载 pdf 文件,以保护文件免受机器人等的侵害。另一个按钮打开一个联系表单,其工作方式大致相同,这是一个允许发送的验证码按钮启用,以及实际发送的表单。该接触部分工作完美,发送消息等。
下载是我遇到问题的地方。它给了我一个 403 错误,从我的故障排除来看,验证码似乎没有被记录,但它必须被记录,否则按钮将无法启用并且不可点击。联系表单部分可以正常工作并发送消息,只是下载无法正常工作。
我尝试了我能想到的一切,甚至尝试使用 ChatGPT 进行一些故障排除,但目前我正在原地踏步。我不是开发人员,但知道的知识足以构成危险。有人可以提供一些指导吗?
以下是经过修订的两个主要文件:
form-handler.js:
document.addEventListener('DOMContentLoaded', function() {
var contactModal = document.getElementById('contactModal');
var downloadModal = document.getElementById('downloadModal');
var notificationPopup = document.getElementById('notificationPopup');
document.getElementById('contactBtn').addEventListener('click', function() {
setupCaptcha('contactModal', 'contactCaptcha', 'RECAPTCHA_SITE_KEY', enableSubmitBtn, 'submitBtn');
});
document.getElementById('downloadBtn').addEventListener('click', function() {
setupCaptcha('downloadModal', 'downloadCaptcha', 'RECAPTCHA_SITE_KEY', enableDownloadBtn, 'downloadLinkBtn');
});
document.getElementById('contactForm').addEventListener('submit', function(event) {
event.preventDefault();
submitForm(this);
});
document.getElementById('downloadLinkBtn').addEventListener('click', initiateDownload);
});
function setupCaptcha(modalId, widgetId, siteKey, callback, buttonId) {
var modal = document.getElementById(modalId);
var container = document.createElement('div');
container.id = widgetId;
container.className = 'g-recaptcha captcha-padding';
container.style.textAlign = 'center';
container.style.display = 'flex';
container.style.justifyContent = 'center';
container.style.padding = '10px 0';
var button = modal.querySelector('#' + buttonId);
button.parentNode.insertBefore(container, button);
window[widgetId] = grecaptcha.render(container, {
'sitekey': siteKey,
'callback': callback
});
}
function enableSubmitBtn() {
document.getElementById("submitBtn").disabled = false;
}
function enableDownloadBtn() {
document.getElementById("downloadLinkBtn").disabled = false;
}
function submitForm(form) {
var recaptchaResponse = grecaptcha.getResponse(window.contactWidgetId);
if (!recaptchaResponse) {
alert("Please complete the CAPTCHA.");
return;
}
var formData = new FormData(form);
formData.append('g-recaptcha-response', recaptchaResponse);
fetch('scripts/phpmailer.php', {
method: 'POST',
body: formData,
})
.then(response => response.json())
.then(data => {
if (data.success) {
alert("Your message has been successfully received. Thank you!");
form.reset();
} else {
alert("There was an error processing your request. Please try again.");
}
})
.catch(error => {
alert("There was an error processing your request. Please try again.");
});
}
function initiateDownload() {
var recaptchaResponse = grecaptcha.getResponse(window.downloadWidgetId);
if (!recaptchaResponse) {
showNotification("Please complete the CAPTCHA.", false);
return;
}
fetch('scripts/download-handler.php', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({captcha: recaptchaResponse}),
credentials: 'include'
})
.then(response => {
if (response.ok) return response.blob();
return response.text().then(text => { throw new Error(text || 'Download failed'); });
})
.then(blob => {
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'SampleFile.pdf'; // Adjust filename as needed
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
})
.catch(error => {
console.error("Error initiating download:", error);
showNotification(error.message, false);
});
}
下载处理程序.php:
<?php
session_start();
// Log session variables for debugging
error_log("Session CAPTCHA completed: " . var_export($_SESSION['captcha_completed'], true));
// Decode JSON input for PHP processing
$_POST = json_decode(file_get_contents("php://input"), true);
if (!isset($_SESSION['captcha_completed']) || $_SESSION['captcha_completed'] !== true) {
http_response_code(403);
echo "CAPTCHA verification failed or session expired.";
exit;
}
$file = '/path/to/your/file.pdf';
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="' . basename($file) . '"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
exit;
} else {
http_response_code(404);
echo "Requested file not available.";
exit;
}
?>
这是浏览器中的控制台输出(如果有帮助的话):
POST https://example.com/scripts/download-handler.php 403 (Forbidden)
initiateDownload @ form-handler.js?ver=1.5.4:80
form-handler.js?ver=1.5.4:100 Error initiating download: Error: CAPTCHA verification failed or session expired.
at form-handler.js?ver=1.5.4:88:53
(anonymous) @ form-handler.js?ver=1.5.4:100
Promise.catch (async)
initiateDownload @ form-handler.js?ver=1.5.4:99
form-handler.js?ver=1.5.4:101 Uncaught (in promise) ReferenceError: showNotification is not defined
at form-handler.js?ver=1.5.4:101:9
非常感谢任何帮助。我不是专家,您很快就会知道。
编辑:我已验证文件和文件夹具有正确的权限,并且位于具有正确路径的正确位置。从下载和测试中删除验证码确实允许下载文件。一旦验证码被放回,403。
编辑2:好的问题解决了,作为一个n00b,我忘记了会话标志。 添加了 set-session.php:
<?php
session_start();
header('Content-Type: application/json'); // Ensure the response is treated as JSON
// Security measure to ensure the request is a POST
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405); // Method Not Allowed
echo json_encode(["error" => "Invalid request method."]);
exit;
}
// Decode JSON input for PHP processing
$input = json_decode(file_get_contents("php://input"), true);
// Check if the CAPTCHA completed field is set and validate it
if (isset($input['captcha_completed']) && $input['captcha_completed'] === true) {
$_SESSION['captcha_completed'] = true;
echo json_encode(["success" => true, "message" => "Session updated successfully."]);
} else {
$_SESSION['captcha_completed'] = false;
http_response_code(400); // Bad request if the parameter is missing or incorrect
echo json_encode(["error" => "Required parameters are missing or incorrect."]);
}
?>
感谢 showdev 和 Daedalus 在我第一次尝试时为我提供了一些急需的指导。对于反对票,谢谢,这些对新手没有帮助,也不太受欢迎。
答案是创建 set-session.php,showdev 让我寻找它。上面是该文件的内容,以防它对未来的新手有所帮助。
我错过了这个帖子的回答按钮,但代达罗斯让我到达那里。谢谢老弟!