验证HTTP请求的来源

5 投票
4 回答
2346 浏览
提问于 2025-04-15 19:17

我有两个系统需要互相通信。它们的设置如下:

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

系统 B,在 Ubuntu/Linux 上运行 Django (Python 2.6),使用 Lighttpd(可能以后会用 nginx)

系统 A 会定期向系统 B 发出请求(我们称之为“请求”),使用 Url Fetch

系统 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()
  ...

其中 verify_request_origin() 函数在请求来自 GAE 上的 系统 A 时返回 true。

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

4 个回答

1

系统A可以通过urlfetch.fetch发送HTTPS请求,只需要确保URL参数以https://开头。不过,这样做并不能让系统B确认请求的身份(虽然可以防止数据被窃听和中间人攻击);也无法使用客户端TLS证书。

想要验证请求确实来自GAE(这其实是可行的:只需使用谷歌自己的DNS服务器8.8.8.8——如果有人能攻破谷歌的DNS,那么他们想要欺骗你的系统B就不是最严重的问题了;-))也没有帮助,原因是一样的:这可能是任何GAE应用(它们共享一堆IP地址,而某个IP地址在短时间内可能被多个GAE应用使用)。

因此,在GAE的限制下,用共享密钥加密数据包似乎是最简单的办法。可以考虑使用PyCrypto——也许在前面加上exPyCrypto会更好;或者,你也可以试试SlowAES(我对后者特别偏爱,当然;-)。

2

听起来只要在链接上使用SSL,并在查询字符串中加入一个密码就可以了。

SSL可以防止别人偷看你的数据,而且你不会把查询信息暴露给你控制之外的系统,所以用一个共享的秘密就足够了(而且比通过IP地址来追踪更安全,因为其他GAE网站也会使用这些地址)。

1

你说得对,前两个要点没什么用。

正如Andrew所说,密码就足够了,除非你担心浏览器缓存的问题。如果你担心这些,那你还是应该使用SSL(安全套接层),不过要通过比如hmac这样的方式来验证一个应用和另一个应用之间的身份,并用它来生成一个会话的共享秘密。这个秘密应该放在代码里,而不是在传输的数据中。

撰写回答