0

我已经实现了一个身份验证方案,它模仿了 Amazon 在我的 Django Web 服务上使用 S3 所做的事情。每个请求都使用秘密进行签名。要签名的字符串包括正在访问的资源的 URL。

例如,如果客户端向http://myservices.org/users发出 GET 请求,则客户端必须构造一个string_to_sign包含http://myservices.org/users. 当服务器处理请求时,它还将构造一个string_to_sign并且可以包含相同的 URL,基于它从 WSGI 包装器请求对象中学习到的信息。

我的问题是,当客户端决定包含端口号(例如http://myservices.org:80/users)时,服务器代码构造不正确string_to_sign,因为我不知道如何获取客户端使用的实际 URL。WSGI 包装器不会让我知道 URL 包含端口号。

有没有办法让 Django 应用程序学习作为 HTTP 请求一部分的实际 URL?我是否需要设置某种位于 WSGI 包装器前面的请求处理程序才能访问原始 HTTP 请求并自己拉出 URL?

4

2 回答 2

1

你要求的是不可能的。您所拥有的只是请求的第一行,其中不包括网络位置(主机名和端口号)。您通常会得到一个 Host 标头(HTTP 1.0 或更高版本),它可能包含也可能不包含端口号。

您可能想查看 django-fost-authn,它实现了与亚马逊非常相似的方案。

即使您不使用它并且更喜欢自己的,您也应该能够在签名前计算中看到请求的规范化是如何完成的。最相关的观察是它只使用 HTTP 请求本身内部的因素。它允许在已签名的标头集中添加自定义标头,并且您可以坚持要对 Host 标头进行签名。

尤其看fost-authn/signature.py中的文档是如何生成的

于 2012-07-06T05:15:17.190 回答
1

尽管它可能并不总是适用于不同的浏览器和 HTTP 版本,但您可以使用request.META['HTTP_HOST']. 对于我现在的本地开发服务器,这将返回“localhost:8000”,然后我可以用中间的冒号将其拆分,以分别获取这两个部分。

此外,您可能会get_host()在 HttpRequest 类的方法中找到一些用途。从Django 文档

使用来自 HTTP_X_FORWARDED_HOST(如果启用 USE_X_FORWARDED_HOST)和 HTTP_HOST 标头的信息,按该顺序返回请求的原始主机。如果它们不提供值,则该方法使用 SERVER_NAME 和 SERVER_PORT 的组合,如 PEP 3333 中所述。

示例:“127.0.0.1:8000”

于 2012-07-06T13:14:47.740 回答