如何限制Django Rest后端请求来源:仅允许React前端与Flutter应用
解决方案:限制Django后端API的合法请求来源
1. 强化CORS配置(仅针对Web前端)
CORS是浏览器层面的跨域限制,对非浏览器客户端(如curl/Postman)无效,所以先把Web前端的访问规则锁死:
- 用
django-cors-headers严格指定允许的源,绝对不能用通配符 - 配置示例:
# settings.py CORS_ALLOWED_ORIGINS = [ "https://mydomain.com", ] CORS_ALLOW_CREDENTIALS = True # 如果前端需要携带Cookie/会话信息
这一步能确保只有你的Web前端域名能通过浏览器发起跨域请求,但挡不住直接调用API的工具。
2. 给Flutter移动端加专属身份校验
Flutter是原生客户端,没有域名标识,得用API密钥或者令牌做身份验证:
- 给Flutter分配一个专属密钥,请求时放在自定义请求头(比如
X-API-Key)里 - 写Django自定义中间件校验这个密钥,同时放行Web前端的合法请求:
# middleware.py from django.http import HttpResponseForbidden class ValidClientMiddleware: def __init__(self, get_response): self.get_response = get_response self.allowed_web_origin = "https://mydomain.com" self.flutter_api_key = "你的Flutter专属密钥" def __call__(self, request): # 先放行Web前端的合法请求(通过Origin头判断) origin = request.headers.get('Origin') if origin == self.allowed_web_origin: return self.get_response(request) # 校验Flutter的API密钥 api_key = request.headers.get('X-API-Key') if api_key != self.flutter_api_key: return HttpResponseForbidden("Invalid client authorization") return self.get_response(request)
然后把这个中间件加到settings.py的MIDDLEWARE列表里,注意要放在corsheaders.middleware.CorsMiddleware之后。
3. 额外措施:拦截非合法客户端
校验User-Agent(基础过滤)
虽然User-Agent可以伪造,但能挡掉大部分普通的curl/Postman请求:
- 在上面的中间件里加一段逻辑:
user_agent = request.headers.get('User-Agent', '') # 允许浏览器和Flutter的User-Agent特征 allowed_ua_patterns = ["Mozilla/5.0", "Dart/"] if origin != self.allowed_web_origin and not any(pattern in user_agent for pattern in allowed_ua_patterns): return HttpResponseForbidden("Unauthorized client")
启用CSRF保护(针对Web前端会话请求)
如果Web前端用了会话认证,开启CSRF保护能进一步确保请求来自你的前端页面:
- 前端Axios配置
withCredentials: true - 后端配置:
CSRF_COOKIE_SECURE = True CSRF_TRUSTED_ORIGINS = ["https://mydomain.com"]
4. Apache层面的辅助限制
在apache2的配置文件里加规则,提前拦截不符合条件的请求:
<Location "/"> # 匹配Web前端的Origin头 SetEnvIf Origin "^https://mydomain\.com$" valid_web_client=1 # 匹配Flutter的API密钥 SetEnvIf X-API-Key "你的Flutter专属密钥" valid_mobile_client=1 # 只允许符合条件的请求 Order Deny,Allow Deny from all Allow from env=valid_web_client Allow from env=valid_mobile_client </Location>
关键注意事项
- Flutter的API密钥不要硬编码在代码里,用环境变量或者后端动态下发的方式管理
- 所有请求必须走HTTPS,防止密钥或请求头被明文窃取
- 没有100%绝对的拦截方案,但组合这些方法能大幅提高API的安全性,过滤绝大多数非法请求
内容的提问来源于stack exchange,提问作者Muhammad Talha Abbas
相关产品推荐
相关产品推荐

