搭建Captive Portal的Python HTTP服务器如何处理带密码保护的文件上传?
解决方案
前端:用FormData上传文件和密码
前端无法解密带密码保护的文件,直接把原始文件二进制和用户输入的密码通过FormData传给服务器即可,这种方式比拼接字符串更可靠,还能兼容各类二进制文件:
// 获取文件输入框和密码输入框 const fileInput = document.getElementById("exa_cli_cert"); const passwordInput = document.getElementById("cert_password"); // 请确保页面有对应密码输入控件 const file = fileInput.files[0]; const password = passwordInput.value; // 构建FormData对象 const formData = new FormData(); formData.append("cert_file", file); // 传入原始文件对象 formData.append("cert_password", password); // 传入密码 // 发送请求 const xhr = new XMLHttpRequest(); xhr.open("POST", "/load/cert"); xhr.onload = function() { if (xhr.status === 201) { console.log("上传处理完成"); } else { console.error("上传失败"); } }; xhr.send(formData);
后端:处理FormData并解密文件
你之前的后端逻辑是处理文本格式POST请求,现在需要改成解析multipart/form-data类型请求,再用对应库解密带密码的文件:
第一步:修改后端接收逻辑(以PKCS#12证书格式为例)
import cgi import os from cryptography.hazmat.primitives import serialization from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.serialization import pkcs12 from http.server import BaseHTTPRequestHandler class YourRequestHandler(BaseHTTPRequestHandler): def do_POST(self): if self.path.endswith('/load/cert'): # 解析multipart/form-data请求 ctype, pdict = cgi.parse_header(self.headers['content-type']) if ctype == 'multipart/form-data': pdict['boundary'] = bytes(pdict['boundary'], "utf-8") form_data = cgi.parse_multipart(self.rfile, pdict) # 提取文件、密码和文件名 cert_file = form_data['cert_file'][0] cert_password = form_data['cert_password'][0].encode("utf-8") # 从请求头提取文件名 file_name = next( part.split('filename=')[1].strip('"') for part in self.headers.get_all('Content-Disposition') if 'filename' in part ) # 先保存原始加密文件(可选步骤) os.makedirs("./certs", exist_ok=True) with open(f"./certs/{file_name}", "wb") as f: f.write(cert_file) # 解密带密码的文件(PKCS#12格式示例) try: private_key, certificate, _ = pkcs12.load_key_and_certificates( cert_file, cert_password, backend=default_backend() ) # 保存解密后的私钥和证书 with open(f"./certs/{file_name}_decrypted.key", "wb") as f: f.write(private_key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=serialization.NoEncryption() )) with open(f"./certs/{file_name}_decrypted.crt", "wb") as f: f.write(certificate.public_bytes(serialization.Encoding.PEM)) except Exception as e: self.send_response(400) self.end_headers() self.wfile.write(f"解密失败:{str(e)}".encode()) return self.send_response(201) self.end_headers() self.wfile.write(b"文件上传并解密成功") else: self.send_response(400) self.end_headers() self.wfile.write(b"不支持的请求格式") else: self.send_response(404) self.end_headers()
第二步:安装依赖库
如果处理的是PKCS#12(.p12/.pfx)格式证书,需要安装加密库:
pip install cryptography
关键注意点
- 必须用
FormData传递二进制文件,不能转成文本传输,否则会损坏文件内容。 - 服务器端解密库要和文件格式匹配:如果是加密ZIP、PDF等其他类型,需更换对应库(比如
pyzipper处理加密ZIP,PyPDF2处理加密PDF)。 - 密码编码要前后端统一,一般用UTF-8即可。
内容的提问来源于stack exchange,提问作者ADM
相关产品推荐
相关产品推荐

