如何验证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"]
- 如果是跨域请求(Cordova和API不在同一域名下),把
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




