You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何验证Cordova应用向Django REST API发送的AJAX文件上传请求

嘿,我完全懂你现在的困境——为了让Cordova的AJAX文件上传请求正常工作,你临时关掉了Django的CSRF防护,但这直接把API暴露给了任何未授权的请求,安全风险拉满。咱们一步步来修复这个问题,既能让文件上传功能正常运行,又能把安全漏洞补上。

1. 重新启用CSRF防护,让Cordova能正确适配

首先,绝对不能一直禁用CSRF,咱们得让Cordova能正确携带CSRF令牌。因为Cordova是原生应用,不像浏览器会自动存储并发送Cookie里的CSRF令牌,所以需要手动处理:

  • 第一步:给Django加一个获取CSRF令牌的简单接口
    在你的Django项目里新增一个视图,专门返回当前用户的CSRF令牌:
    # views.py
    from django.middleware.csrf import get_token
    from django.http import JsonResponse
    
    def get_csrf_token(request):
        return JsonResponse({'csrfToken': get_token(request)})
    
    然后在urls.py里给这个视图加路由,比如:
    path('api/get-csrf-token/', views.get_csrf_token, name='get_csrf_token'),
    
  • 第二步:修改Cordova的AJAX代码,先拿令牌再上传
    先调用上面的接口拿到CSRF令牌,再在上传请求的请求头里带上X-CSRFToken字段。另外注意你原代码里的选择器$('upload')应该是$('#upload'),我一起帮你修正了:
    // 先获取CSRF令牌
    fetch('/api/get-csrf-token/')
      .then(response => response.json())
      .then(data => {
        const csrfToken = data.csrfToken;
        // 执行文件上传逻辑
        var formid = document.getElementById('upload');
        var url = $('#upload').attr('action');
        var form = new FormData(formid);
        var remark = document.getElementById('remarkt').value;
        form.append("remark", remark);
        form.append("file", $("#filet")[0].files[0]);
        
        var settings = {
          "async": true,
          "crossDomain": true,
          "url": url,
          "method": "POST",
          "headers": {
            "X-CSRFToken": csrfToken, // 关键:带上CSRF令牌
            // 别手动加Content-Type!FormData会自动处理多表单数据的格式
          },
          "processData": false,
          "contentType": false,
          "mimeType": "multipart/form-data",
          "data": form
        };
        
        $.ajax(settings).done(function (response) {
          console.log(response);
        });
      });
    
  • 额外配置:确保Django的settings.py里做这些设置
    • 如果是跨域请求(Cordova和API不在同一域名下),把SESSION_COOKIE_SAMESITE设为None,同时CSRF_COOKIE_SECURE在生产环境设为True(开发环境可暂时设为False
    • CSRF_TRUSTED_ORIGINS里添加你Cordova应用的信任域名,比如["https://your-cordova-app-domain.com"]
2. 加上身份认证,确保只有授权用户能访问API

光有CSRF还不够,得确保请求来自合法用户,推荐用Token认证(最适合Cordova这类原生应用):

  • 第一步:配置DRF的Token认证
    安装DRF的Token支持,然后在settings.py里配置:
    # settings.py
    INSTALLED_APPS = [
        # 其他App...
        'rest_framework',
        'rest_framework.authtoken', # 添加这个
    ]
    
    REST_FRAMEWORK = {
        'DEFAULT_AUTHENTICATION_CLASSES': [
            'rest_framework.authentication.TokenAuthentication',
        ],
        'DEFAULT_PERMISSION_CLASSES': [
            'rest_framework.permissions.IsAuthenticated', # 强制只有登录用户能访问API
        ]
    }
    
    然后运行python manage.py migrate生成Token表。
  • 第二步:Cordova端存储并携带Token
    用户登录时,你的API返回一个Token,Cordova把它存在localStorage里,之后每次请求都在请求头里带上:
    // 在settings的headers里新增Authorization字段
    "headers": {
      "X-CSRFToken": csrfToken,
      "Authorization": "Token " + localStorage.getItem('authToken')
    },
    
3. 额外的安全加固小技巧
  • 验证上传文件:在Django视图里检查文件类型、大小,比如只允许图片、PDF等特定格式,限制单文件大小不超过10MB,防止恶意文件上传
  • 生产环境强制HTTPS:避免令牌和数据被窃听
  • 短生命周期令牌:如果用JWT替代普通Token,设置较短的过期时间,配合刷新令牌机制,降低令牌泄露的风险
  • 移除所有csrf_exempt装饰器:确保所有API视图都受CSRF防护

现在你可以把之前禁用CSRF的代码去掉了,这样既保证了Cordova应用能正常上传文件,又能阻止未授权的请求访问你的API。

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

火山引擎 最新活动