如何创建接收单次请求即终止的Python简易HTTPS服务器?
最简Python SSL服务器问题解决(用于Slack OAuth重定向)
需求目标
- 搭建仅接收一次请求后即终止的最简Python服务器,用于接收Slack OAuth链接的重定向响应
第一版代码及问题
代码实现
import http.server from ssl import SSLContext class MyHandler(http.server.SimpleHTTPRequestHandler): def do_POST(self): content_length = int(self.headers['Content-Length']) post_data = self.rfile.read(content_length) print(post_data.decode('utf-8')) server_address = ('127.0.0.1', 5000) httpd = http.server.HTTPServer(server_address, http.server.SimpleHTTPRequestHandler) httpd.socket = SSLContext().wrap_socket(sock=httpd.socket, server_side=True, do_handshake_on_connect=False, suppress_ragged_eofs=True) httpd.serve_forever()
出现的错误
- 废弃警告:
ssl.SSLContext()无协议参数已废弃,ssl.PROTOCOL_TLS已废弃 - SSL握手错误:
ssl.SSLError: [SSL: NO_SHARED_CIPHER] no shared cipher,更换多个端口仍无法解决
第二版代码及新问题
用户通过以下openssl命令生成证书和密钥:
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365
更新后的代码
import http.server import ssl class MyHandler(http.server.SimpleHTTPRequestHandler): def do_POST(self): content_length = int(self.headers['Content-Length']) post_data = self.rfile.read(content_length) print(post_data.decode('utf-8')) server_address = ('127.0.0.1', 5000) httpd = http.server.HTTPServer(server_address, MyHandler) context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) context.load_cert_chain(certfile="cert.pem", keyfile="key.pem") httpd.socket = context.wrap_socket(httpd.socket, server_side=True) httpd.serve_forever()
新问题
脚本卡在load_cert_chain步骤无响应
解决方案
1. 解决证书加载无响应问题
生成证书时若未设置密码,load_cert_chain可能会等待输入密码(即使无密码也可能触发),可明确指定无密码:
context.load_cert_chain(certfile="cert.pem", keyfile="key.pem", password=None)
或者重新生成证书时直接跳过密码设置:
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
(-nodes参数表示不加密私钥,无需输入密码)
2. 实现接收一次请求后终止
修改服务器逻辑,处理完请求后立即关闭:
import http.server import ssl class MyHandler(http.server.SimpleHTTPRequestHandler): def do_GET(self): # Slack OAuth重定向为GET请求,需替换原POST逻辑 print("Received OAuth redirect:", self.path) # 返回成功响应 self.send_response(200) self.send_header('Content-type', 'text/html') self.end_headers() self.wfile.write(b"Authorization received! You can close this window.") # 处理完成后关闭服务器 self.server.shutdown() server_address = ('127.0.0.1', 5000) httpd = http.server.HTTPServer(server_address, MyHandler) # 初始化TLS服务器上下文 context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) context.load_cert_chain(certfile="cert.pem", keyfile="key.pem", password=None) httpd.socket = context.wrap_socket(httpd.socket, server_side=True) # 仅处理一次请求后退出 httpd.handle_request()
注意:Slack OAuth的重定向默认是GET请求,需实现
do_GET方法而非do_POST
3. 验证证书有效性
若证书生成异常会导致加载失败,可通过以下命令验证:
# 验证证书内容 openssl x509 -in cert.pem -text -noout # 验证私钥有效性 openssl rsa -in key.pem -check
关键注意事项
- 必须使用
ssl.PROTOCOL_TLS_SERVER作为SSL上下文协议,避免废弃警告 - 确保证书和私钥文件与脚本在同一目录,或使用绝对路径指定
- Slack OAuth重定向请求类型为GET,需对应调整请求处理方法
内容的提问来源于stack exchange,提问作者Mika
相关产品推荐
相关产品推荐

