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

如何在Django View中查看传入请求的SSL证书内容?

在Django View中获取并验证请求方SSL证书的方法

要实现这个需求,核心是两步:让Web服务器将客户端证书信息传递给Django,然后在View中提取并验证证书。

前提配置:让反向代理传递客户端证书

生产环境中,Django通常搭配Nginx/Apache这类反向代理处理SSL请求。你需要配置反向代理:

  1. 要求客户端在建立SSL连接时提供证书
  2. 将客户端证书的PEM格式内容通过HTTP请求头传递给Django

以Nginx为例,添加以下配置:

server {
    listen 443 ssl;
    server_name your-api-domain.com;

    # 配置服务器证书
    ssl_certificate /path/to/your/server.crt;
    ssl_certificate_key /path/to/your/server.key;

    # 要求客户端提供证书,并指定信任的CA证书
    ssl_client_certificate /path/to/your/trusted-ca.crt;
    ssl_verify_client on;

    # 将客户端证书传递给Django
    location / {
        proxy_pass http://your-django-server:8000;
        proxy_set_header SSL_CLIENT_CERT $ssl_client_cert;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

在Django View中获取并验证证书

配置完成后,客户端证书会以PEM格式字符串的形式出现在request.META中,对应的键是HTTP_SSL_CLIENT_CERT(反向代理的请求头会被WSGI转换为大写并添加HTTP_前缀)。

示例View代码:

from django.http import HttpResponseForbidden, HttpResponse
from cryptography import x509
from cryptography.hazmat.backends import default_backend
import datetime

def validated_post_endpoint(request):
    if request.method != "POST":
        return HttpResponseForbidden("Only POST requests are allowed")

    # 提取客户端证书
    cert_pem = request.META.get("HTTP_SSL_CLIENT_CERT")
    if not cert_pem:
        return HttpResponseForbidden("No client certificate provided")

    try:
        # 解析PEM格式证书
        cert = x509.load_pem_x509_certificate(cert_pem.encode(), default_backend())

        # 1. 验证证书由信任的CA签发
        with open("/path/to/your/trusted-ca.crt", "rb") as ca_file:
            ca_cert = x509.load_pem_x509_certificate(ca_file.read(), default_backend())
        cert.verify_directly_issued_by(ca_cert)

        # 2. 验证证书有效期
        now = datetime.datetime.now(datetime.timezone.utc)
        if not (cert.not_valid_before <= now <= cert.not_valid_after):
            return HttpResponseForbidden("Certificate has expired or is not yet valid")

        # 3. 验证证书主题(比如检查CN是否为指定服务器)
        common_name = cert.subject.get_attributes_for_oid(x509.NameOID.COMMON_NAME)[0].value
        if common_name != "authorized-server.example.com":
            return HttpResponseForbidden("Invalid certificate subject")

    except Exception as e:
        return HttpResponseForbidden(f"Certificate validation failed: {str(e)}")

    # 证书验证通过,处理POST请求业务逻辑
    # ... 你的业务代码 ...
    return HttpResponse("Request authenticated successfully")

关键注意事项

  • 生产环境禁止用Django自带runserver处理SSL:runserver仅用于开发,必须用反向代理处理SSL连接。
  • 不要仅检查证书存在:必须验证证书的签发机构、有效期、主题等核心信息,防止伪造证书绕过验证。
  • 依赖cryptography库:需要先执行pip install cryptography安装证书解析和验证工具。

内容的提问来源于stack exchange,提问作者AmrElsayed

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 21:02:10