如何将 django 端点限制为本地网络?

Posted

技术标签:

【中文标题】如何将 django 端点限制为本地网络?【英文标题】:How to restrict django endpoint to localnetwork? 【发布时间】:2021-09-20 09:18:12 【问题描述】:

在我的项目中,我使用许多 FastAPI 微服务来执行指定的任务,并使用 Django 应用程序来处理用户操作、连接前端等。 在 Django 数据库中,我存储有关微服务应获取的文件路径的信息。我只想将它提供给微服务和这个微服务。所以我想限制对端点的访问到本地网络上的指定端口。

其他端点通常应可用于 Web 应用程序。仅使用 Django cors 标头将不起作用,因为我希望正常访问大多数端点并将其限制为 localhost 仅用于一小部分子集。

CORS_ORIGIN_WHITELIST = [
    "http://my_frontend_app" # most of the endpoints available from the front end
    "http://localhost:9877", #the microservice that I want to provide with the path
]

另一种解决方案可能是使用from corsheaders.signals import check_request_enabled,但在the use cases that I have seen 中,它通常用于扩大访问范围,而不是限制它(前端不应访问端点子集)。我不确定这是否是一个好的解决方案。

# myapp/handlers.py
from corsheaders.signals import check_request_enabled

def cors_allow_particular_urls(sender, request, **kwargs):
    return request.path.startswith('/public-api/')

check_request_enabled.connect(cors_allow_mysites)

有什么方法可以创建“本地 cors”,例如,以装饰器的形式?它看起来像:

@local_cors([“localhost:9877”])
@decorators.action(detail=False, methods=["post"])
def get_data(self, request):
    return response.Response(status=200)

localhost:9877 是微服务的地址

这样的解决方案是否足够好?

def get_data(self, request):
    
    request_host = request.get_host()
    data = request.data

     if request_host != MAP_UPLOAD_HOST:
        # we don't show the endpoint to the outside return       
        response.Response(status=404)
    
    return response.Response(status=200)

【问题讨论】:

如果你真的只想允许一个调用者访问,CORS 是不够的:有人可以通过其他方式访问该视图(甚至可能不使用 Web 浏览器)。这有关系吗? 是的。 CORS 不足以限制访问? CORS 仅由 Web 浏览器强制执行,以防止将信息泄漏到可能请求它的不相关页面。您需要某种访问控制,方法是对调用者进行身份验证或限制对相关 URL 的访问。 所以我应该通过使用类似“if request.headers['Origin'] == "localhost:9877"? 【参考方案1】:

使用get_host() 检查Host 标头可能提供足够的保护,具体取决于您的服务器设置。

get_host() 将告诉您请求中Host 标头的值,这是客户端提供的数据,因此可以以任何方式进行操作。 Host 标头是 HTTP 1.1 的一个组成部分,它允许多个域托管在一​​个地址上,因此您可以依靠您的服务器拒绝实际上不是来自 localhost 并带有匹配标头的请求,但很难确定。

check the client's network address 可能更可靠,并拒绝所有客户端的请求,特别允许的请求除外。

【讨论】:

以上是关于如何将 django 端点限制为本地网络?的主要内容,如果未能解决你的问题,请参考以下文章

Django如何将模板限制为只有两个帖子

如何将媒体文件的 URL 限制为 Django 中未经身份验证的用户?

将 GCP API 密钥限制为给定 API 的端点子集

如何将 Django Rest Framework 可浏览 API 接口限制为管理员用户

将 django FloatField 限制为 2 位小数

如何在Django Admin中将ImageField限制为几个选项