我已经实现了一种身份验证方案,模仿亚马逊在我的Django Web服务上使用S3做的事情。每个请求都使用机密签名。要签名的字符串包括所访问资源的URL。
例如,如果客户端发出http://myservices.org/users的GET请求,则客户端必须构建包含string_to_sign
的{{1}}。当服务器处理请求时,它还将构造一个http://myservices.org/users
,并且可以根据从WSGI包装器请求对象获知的信息包含相同的URL。
我的问题是,当客户端决定包含端口号(例如string_to_sign
)时,服务器代码会构造一个不正确的http://myservices.org:80/users
,因为我不知道如何获取实际的URL客户使用。 WSGI包装器不让我知道URL包含端口号。
有没有办法让Django应用程序学习属于HTTP请求的实际URL?我是否需要设置某种位于WSGI包装器前面的请求处理程序,以便访问原始HTTP请求并自行提取URL?
答案 0 :(得分:1)
你要求不可能的事。您所拥有的只是请求的第一行,不包括网络位置(主机名和端口号)。您通常会获得一个主机头(HTTP 1.0或更高版本),其中可能包含或不包含端口号。
你可能想看看django-fost-authn,它实现了一个与亚马逊非常类似的方案。
即使您不使用它并且更喜欢自己的,您也应该能够看到如何在预签名计算中完成请求的规范化。最相关的观察是它只使用HTTP请求本身内部的因子。它允许添加自定义标头以包含在已签名的标头集中,您可以坚持认为主机标头已签名。
特别注意如何在fost-authn / signature.py
中生成文档答案 1 :(得分:1)
虽然它可能并不总是适用于不同的浏览器和HTTP版本,但您可以使用request.META['HTTP_HOST']
。对于我的本地开发服务器,现在返回“localhost:8000”,然后我可以通过中间的冒号拆分以分别获得两个部分。
此外,您可能会在HttpRequest类的get_host()
方法中找到一些用法。来自the Django documentation:
使用来自HTTP_X_FORWARDED_HOST(如果已启用USE_X_FORWARDED_HOST)和HTTP_HOST标头的信息按此顺序返回请求的发起主机。如果它们没有提供值,则该方法使用SERVER_NAME和SERVER_PORT的组合,如PEP 3333中所述。
示例:“127.0.0.1:8000”