Python Django应用:如何阻止用户通过浏览器URL访问GET接口数据
解决Django中阻止浏览器直接GET访问、区分代码调用与浏览器请求的问题
嘿,这个场景我太熟悉了!只用sessionid确实没法区分请求是来自浏览器手动输入URL,还是代码/前端AJAX的合法调用——毕竟只要会话有效,两种请求都会带上session凭证。下面给你几个实用的解决方案,你可以根据自己的业务场景选择:
方案1:检查自定义请求头(最推荐)
核心思路是让合法的代码/前端调用主动携带一个自定义请求头,而浏览器直接输入URL时不会包含这个头。在视图里验证这个头的存在和正确性,就能拦截非法访问。
后端视图代码
from django.http import HttpResponseForbidden from django.http import JsonResponse def protected_data_view(request): if request.method == 'GET': # 检查自定义请求头,这里用X-Requested-By作为示例,你可以自定义名称 valid_header = request.META.get('HTTP_X_REQUESTED_BY') if valid_header != 'Your-App-Client': return HttpResponseForbidden("Direct browser access is not allowed.") # 这里处理正常的GET请求逻辑,返回数据 return JsonResponse({"data": "your protected content"}) # 处理其他请求方法(如POST) # ...
代码调用示例(比如用requests库)
import requests url = "http://your-domain.com/protected-data/" headers = { "X-Requested-By": "Your-App-Client", "Cookie": "sessionid=your-session-id" # 如果需要会话认证的话 } response = requests.get(url, headers=headers)
前端AJAX示例(fetch)
fetch('/protected-data/', { method: 'GET', headers: { 'X-Requested-By': 'Your-App-Client', 'X-CSRFToken': document.cookie.split('; ').find(row => row.startsWith('csrftoken=')).split('=')[1] } }) .then(response => response.json()) .then(data => console.log(data));
这个方案的优势是可靠性高,普通用户很难在浏览器地址栏直接添加自定义请求头,足以应对大部分场景。
方案2:检查X-Requested-With头(适配AJAX场景)
如果你的请求主要来自前端AJAX调用,可以利用传统AJAX请求会携带的X-Requested-With: XMLHttpRequest头。注意:Django 3.1之后request.is_ajax()方法已被弃用,需要手动检查这个头。
from django.http import HttpResponseForbidden from django.http import JsonResponse def ajax_protected_view(request): if request.method == 'GET': is_ajax_request = request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest' if not is_ajax_request: return HttpResponseForbidden("Only AJAX requests are allowed.") # 正常处理请求 return JsonResponse({"data": "ajax-only content"})
这个方案适合纯前端AJAX调用的场景,但要注意:如果用户用开发者工具手动添加这个头,也能绕过拦截,适合对安全性要求不是极高的内部系统。
方案3:检查Referer头(辅助验证,不单独使用)
通过检查请求的Referer头,判断请求是否来自你的站点内部(比如从你的前端页面跳转过来)。但这个方法局限性很大,因为Referer可能被浏览器或安全工具屏蔽,也容易被伪造,所以建议只作为辅助验证手段。
from django.http import HttpResponseForbidden from django.http import JsonResponse def referer_protected_view(request): if request.method == 'GET': referer = request.META.get('HTTP_REFERER') # 验证Referer是否来自你的域名 if not referer or not referer.startswith('https://your-domain.com'): return HttpResponseForbidden("Direct access not allowed.") # 处理请求 return JsonResponse({"data": "referer-validated content"})
额外注意事项
- 以上方法都无法完全阻止技术熟练的用户伪造请求,如果需要更高安全性,可以结合API密钥、OAuth2等认证机制。
- 如果你是前后端分离项目,需要确保跨域配置允许自定义请求头的传递。
- 测试时记得分别用浏览器直接访问URL(应该返回403)和合法代码/前端调用(应该正常返回数据)验证效果。
内容的提问来源于stack exchange,提问作者Ramesh
相关产品推荐
相关产品推荐

