Flask端点客户端证书解析与验证:提取commonName及优化证书获取方案
解析客户端证书字符串并提取commonName的方案,以及更优的证书获取方式
首先,针对你现在拿到的这种Python字典字面量格式的字符串,最安全的解析方式是用ast.literal_eval()——它专门用来解析Python的字面量结构(比如字典、元组、列表等),比直接用eval()安全得多,不会执行恶意代码。
步骤1:解析字符串并提取commonName
修改你的代码,用ast.literal_eval()解析证书字符串,再遍历嵌套的元组结构找到commonName:
import ast from flask import request, Flask app = Flask(__name__) @app.route('/predict', methods=['POST']) def predict(): res = "hi" status = False if request.url.startswith('https://'): client_cert_str = request.headers["CLIENT_CERT"] # 把字符串解析为Python字典 client_cert = ast.literal_eval(client_cert_str) # 从嵌套元组的subject中提取commonName common_name = None for field_group in client_cert['subject']: for key, value in field_group: if key == 'commonName': common_name = value break if common_name: break print(f"客户端证书CN: {common_name}") # 这里添加你的格式验证逻辑 if common_name and common_name.endswith('.domainname.com'): status = True res = "认证通过" else: res = "CN格式不符合要求" return res, 200 if status else 403
更优的客户端证书获取方式
其实你现在通过请求头传递证书的方式不是最优解,更规范的做法是让WSGI服务器(比如Gunicorn、uWSGI)直接处理客户端证书验证,并将解析后的证书信息注入到Flask的request.environ中。
以Gunicorn为例的配置与代码实现
- 启动Gunicorn时开启强制客户端证书验证:
gunicorn --certfile=server.crt --keyfile=server.key --ca-certs=ca.crt --cert-req=2 app:app
这里--cert-req=2表示强制要求客户端提供证书,--ca-certs指定用来验证客户端证书的信任CA证书。
- 在Flask中直接获取并解析证书:
此时request.environ会包含SSL相关的环境变量,你可以用cryptography库直接解析PEM格式的证书,获取结构化的信息:
from cryptography import x509 from cryptography.hazmat.backends import default_backend from flask import request, Flask app = Flask(__name__) @app.route('/predict', methods=['POST']) def predict(): res = "hi" status = False if request.url.startswith('https://'): # 从环境变量获取PEM格式的客户端证书 client_cert_pem = request.environ.get('SSL_CLIENT_CERT') if client_cert_pem: # 解析证书为结构化对象 cert = x509.load_pem_x509_certificate( client_cert_pem.encode(), default_backend() ) # 直接提取commonName common_name = cert.subject.get_attributes_for_oid(x509.NameOID.COMMON_NAME)[0].value print(f"客户端证书CN: {common_name}") # 执行格式验证 if common_name.endswith('.domainname.com'): status = True res = "认证通过" else: res = "CN格式不符合要求" return res, 200 if status else 403
这种方式的优势:
- 避免手动传递证书字符串的麻烦和格式问题
- 由服务器层强制验证证书的有效性(比如是否由信任CA签发、是否过期),安全性更高
- 可以直接获取完整的证书对象,方便提取有效期、颁发者等更多字段
内容的提问来源于stack exchange,提问作者Daniel Qiao
相关产品推荐
相关产品推荐

