验证HTTP请求的来源

时间:2010-02-14 21:26:58

标签: python django google-app-engine encryption cryptography

我有两个需要交谈的系统。这些系统设置为:

System A,在Google App Engine(GAE)上运行Django(Python 2.5)

System B,通过Lighttpd在Ubuntu / Linux上运行Django(Python 2.6)(可能是后来的nginx)

系统A将使用Url Fetch定期发出系统B的请求('请购单')。

系统B有一个Django应用程序设置,可以使用urls.py来监听这些请求,例如:

urlpatterns = patterns('producer.views',
    url(r'^requisition$', 'requisition', name='requisition'),
)

和相应的views.py类似:

import json
from django.http import HttpResponse

def requisition(request):
    " do something "
    response = HttpResponse()
    response['Content-type'] = 'application/json'
    response.write(json.dumps(...))
    return response

如果系统B仅响应来自系统A的请购单,则对系统的安全性将是一个有价值的补充。

我想知道系统B可以使用哪些选项来验证请求是否来自系统A.我已经考虑过以下内容:

  • 检查IP地址是否来自GAE(但我不知道GAE IP地址,它们可能会更改,并且可能会被欺骗)
  • 检查IP的反向DNS是否来自GAE(但我不知道GAE的DNS条目是什么,如果它们会改变,它们可能会被欺骗)
  • 使用系统A的TLS客户端证书 - 但我不知道如何使用GAE
  • 执行此操作
  • 根据与pycrypto
  • 共享的内容(如盐)进行质询/回复

理想情况下,我希望最终得到views.py,其中包含以下内容:

... 
from django.http import HttpResponseForbidden 

def requisition(request):
   " do something "
  if not verify_request_origin():
     return HttpResponseForbidden("Denied.")

  response = HttpResponse()
  ...

System B的请求来自GAE上的System A时,verify_request_origin()返回true。

谢谢你,我期待着听到你的想法。

4 个答案:

答案 0 :(得分:2)

听起来在链接上使用SSL并在查询字符串中包含密码就足够了。

SSL阻止了嗅探器,并且您不会在您控制的系统之外泄露查询,因此共享密钥将会执行(并且将比IP跟踪更安全,因为其他GAE站点将使用这些地址)。

答案 1 :(得分:1)

你是现场,前两个要点是没用的。

密码Andrew表示足够好,除非您担心浏览器缓存问题。如果您是,那么您仍然应该使用SSL,但是要通过例如hmac向另一个应用程序验证一个应用程序,并使用它来为会话生成共享密钥。秘密应该存在于代码中,而不是传输的数据中。

答案 2 :(得分:1)

系统A可以通过urlfetch.fetch发送HTTPS请求 - 只需将URL参数以https://开头即可。然而,这并没有对系统B进行身份验证(它确实可以防止嗅探器和中间人攻击);没有办法使用客户端TLS证书。

验证请求是否来自GAE(这是完全可行的:只需使用Google自己的DNS服务器8.8.8.8 - 如果某人设法使用谷歌自己的DNS,他们欺骗你的系统B的能力将是最少的世界的担忧;-)也没有帮助,原因相同:它可能是任何 GAE应用程序(它们共享一堆IP地址,任何IP地址都可以使用短时间内GAE应用程序的数量。)

因此,考虑到GAE的限制,使用共享密钥加密有效载荷似乎最简单。 PyCrypto - 也许前面有exPyCrypto - 可能会很好;或者,您可能想尝试SlowAES(当然,我对后者有一个弱点; - )。

答案 3 :(得分:1)

一个防弹选项是查看FOAF + SSL http://www.w3.org/wiki/Foaf%2Bssl/FAQ#What_is_FOAF.2BSSL