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

如何限制DRF邮件提交API仅接受自有网站表单的请求?

限制DRF邮件API仅接受自有网站请求的几种方案

针对你的需求,这里有几个实用的方法来限制API的访问来源,确保只有你自有网站的表单能调用这个邮件接口:

1. 检查HTTP Referer请求头

浏览器提交表单时会自动带上Referer头,记录请求发起的页面地址。我们可以在视图里验证这个头是否属于你的域名:

修改你的send_email函数,在处理POST请求前加入Referer校验:

from rest_framework import status
from rest_framework.response import Response
from rest_framework.decorators import api_view
from django.conf import settings
from django.core.mail import send_mail

@api_view(['POST'])
def send_email(request):
    # 新增:校验Referer头
    ALLOWED_DOMAINS = ['https://yourdomain.com', 'https://www.yourdomain.com']  # 替换成你的实际域名
    referer = request.META.get('HTTP_REFERER')
    
    if not referer:
        return Response({"error": "请求来源无效"}, status=status.HTTP_403_FORBIDDEN)
    
    # 检查Referer是否以允许的域名开头
    is_allowed = any(referer.startswith(domain) for domain in ALLOWED_DOMAINS)
    if not is_allowed:
        return Response({"error": "拒绝访问"}, status=status.HTTP_403_FORBIDDEN)
    
    # 原有业务代码
    if request.method == 'POST':
        name = request.data.get("name")
        email = request.data.get("email")
        subject = request.data.get("subject")
        message = request.data.get('message')

        message_con = 'Message: ' + message + '\nEmail: ' + email + '\nName of the sender: ' + name
        print("sent via POST")
        try:
            send_mail(subject, message_con, settings.EMAIL_HOST_USER, ['someemail@gmail.com'])
            return Response({"message": _("Email Successfully sent!")})
        except Exception as e:
            print(e)
            return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
            
    return Response({"error": _("Method Not Allowed.")}, status=status.HTTP_405_METHOD_NOT_ALLOWED)

提示:Referer头存在被伪造的可能,但对于普通恶意请求已足够,适合快速实现基础访问限制。

2. 启用CSRF保护

DRF默认对函数视图关闭了CSRF验证,但你的场景是自有网站的浏览器表单提交,可以开启CSRF保护,只有带正确CSRF令牌的请求才能通过:

步骤1:给视图添加CSRF保护装饰器

from django.views.decorators.csrf import csrf_protect
from rest_framework.decorators import api_view

@api_view(['POST'])
@csrf_protect  # 新增该装饰器启用CSRF验证
def send_email(request):
    # 原有业务代码不变

步骤2:前端表单中加入CSRF令牌

在你的HTML表单里添加Django的CSRF令牌模板标签,确保提交时带上令牌:

<form method="post" action="/path/to/send_email/">
    {% csrf_token %}
    <!-- 其他表单字段:name、email、subject、message -->
    <button type="submit">发送邮件</button>
</form>

这种方法是浏览器原生的安全机制,能有效防止跨站请求伪造,完全适配自有网站的表单场景。

3. 配置CORS策略(针对单页应用场景)

如果你的前端是React/Vue这类单页应用,通过AJAX提交请求,可以用django-cors-headers库限制允许访问API的域名:

步骤1:安装依赖

pip install django-cors-headers

步骤2:配置Django settings

# settings.py
INSTALLED_APPS = [
    # ... 其他已安装应用
    'corsheaders',
]

MIDDLEWARE = [
    # 放在CommonMiddleware之前
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    # ... 其他中间件
]

# 仅允许你的域名访问API
CORS_ALLOWED_ORIGINS = [
    "https://yourdomain.com",
    "https://www.yourdomain.com",
]

提示:CORS是浏览器层面的限制,服务器端仍可能被直接调用,建议结合Referer校验或CSRF保护一起使用,提升整体安全性。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 08:56:06