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

AngularJS前端POST请求Django接口返回403错误排查

问题定位

Postman可正常响应、Angular前端POST返回403,核心是配置错误、自定义中间件逻辑异常、前后端CSRF规则不匹配三类问题,和基础CORS开关是否打开无关。

具体错误点

  • 存在无效配置项:CSRF_WHITELIST_ORIGINS是Django不存在的配置参数,框架不会读取该配置,写了也不生效。
  • CSRF配置混淆Cookie名和请求头名:将CSRF_COOKIE_NAME(Django写入客户端的CSRF校验Cookie的名称,默认值为csrftoken)错误设置为X-CSRFToken——后者是前端发请求时携带CSRF值的请求头名称,二者搞混会导致前端无法读取到正确的CSRF校验值。
  • 缺少跨域凭证配置:未开启CORS_ALLOW_CREDENTIALS,跨域场景下浏览器不会向前端发送Cookie、也不会允许前端携带Cookie发起请求,直接导致CSRF校验、会话认证失败。
  • 自定义会话中间件逻辑错误:
    1. 会话续期逻辑写反:注释说明要给已认证用户延长会话,但实际set_expiry(86400)的续期逻辑写在了未认证用户的else分支,已登录用户根本不会触发续期。
    2. 非法调用CSRF中间件:在自定义中间件中手动实例化CsrfViewMiddleware时传入字符串'get_response'作为参数,该参数要求是可调用的请求处理链对象,传字符串会直接触发运行异常,干扰Django默认的全局CSRF校验流程。Django默认已全局加载CSRF中间件,不需要在自定义业务中间件中重复调用。
  • 前后端CSRF规则不匹配:AngularJS默认读取的CSRF Cookie名为XSRF-TOKEN,发起请求时默认携带的CSRF请求头名为X-XSRF-TOKEN,和Django默认的Cookie名、要求的请求头名完全不匹配,就算后端配置正确,Angular也不会自动携带正确的CSRF校验值。

Postman不受浏览器同源策略约束,不存在跨域Cookie拦截、自动请求头缺失的限制,所以可以正常响应,和浏览器环境下的前端请求逻辑有本质区别。


修正步骤

1. 修正settings.py配置

删除无效配置,修正错误参数,补全跨域必要配置:

# 跨域白名单配置
CORS_ORIGIN_WHITELIST = [
    'http://localhost:8000',
    'http://localhost:8080',
]
# 允许跨域请求携带Cookie、认证凭证
CORS_ALLOW_CREDENTIALS = True
# 配置跨域允许的请求头,包含CSRF请求头
CORS_ALLOW_HEADERS = [
    'accept',
    'accept-encoding',
    'authorization',
    'content-type',
    'dnt',
    'origin',
    'user-agent',
    'x-csrftoken',
    'x-requested-with',
]

# CSRF信任源配置,删除无效的CSRF_WHITELIST_ORIGINS参数
CSRF_TRUSTED_ORIGINS = [
    'http://localhost:8000',
    'http://localhost:8080',
]

# 会话基础配置
SESSION_COOKIE_PATH='/'
SESSION_COOKIE_SECURE=False
SESSION_COOKIE_DOMAIN=None
SESSION_COOKIE_HTTPONLY=False
SESSION_EXPIRE_AT_BROWSER_CLOSE = False
SESSION_COOKIE_AGE = 86400 

# 修正CSRF Cookie配置,Cookie名恢复为默认值csrftoken,不要与请求头名混淆
CSRF_COOKIE_NAME='csrftoken'
CSRF_COOKIE_AGE=86400
CSRF_COOKIE_DOMAIN=None
CSRF_COOKIE_HTTPONLY=False
CSRF_COOKIE_PATH='/'
CSRF_COOKIE_SECURE=False

2. 重写自定义会话中间件

删除错误的CSRF手动调用逻辑,修正会话续期的分支判断:

from django.utils.deprecation import MiddlewareMixin

class ExtendUserSession(MiddlewareMixin):
    """
    延长已认证用户的会话有效期,避免用户频繁重新登录
    会话有效期取86400秒(1天)
    """
    def process_request(self, request):
        # 仅对已登录用户刷新会话过期时间
        if request.user.is_authenticated:
            request.session.set_expiry(86400)

将该中间件添加到settings.py的MIDDLEWARE列表中,位置放在SessionMiddleware之后、CsrfViewMiddleware之前,不要打乱Django默认中间件的顺序。

3. 配置AngularJS侧CSRF适配

在AngularJS应用启动配置块中,对齐Django的CSRF规则,开启跨域凭证携带:

angular.module('yourApp', [])
  .config(['$httpProvider', function($httpProvider) {
    // 对齐Django侧的CSRF Cookie名
    $httpProvider.defaults.xsrfCookieName = 'csrftoken';
    // 对齐Django侧要求的CSRF请求头名
    $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
    // 全局开启跨域请求携带凭证
    $httpProvider.defaults.withCredentials = true;
  }]);

验证操作

所有配置修改完成后,清空浏览器本地存储的当前站点所有Cookie(清除之前错配生成的无效CSRF Cookie、会话Cookie),重启Django服务后重新发起请求即可正常响应。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 16:57:18