You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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为例的配置与代码实现

  1. 启动Gunicorn时开启强制客户端证书验证:
gunicorn --certfile=server.crt --keyfile=server.key --ca-certs=ca.crt --cert-req=2 app:app

这里--cert-req=2表示强制要求客户端提供证书,--ca-certs指定用来验证客户端证书的信任CA证书。

  1. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 07:02:37