如何保护我在应用内发起的REST调用?
我有一个应用程序,它有一个“私有”的REST API;我在自己的网站上使用RESTful的URL进行Ajax调用。不过,这样不安全,任何人只要知道这些URL的格式,就可以进行相同的调用。
有什么好的(或者说是标准的)方法来保护这些调用吗? 如果我打算将来发布一个API,现在考虑使用像OAuth这样的东西是否值得,还是说我把两种不同的策略搞混了?
我正在使用Google App Engine和Python,以及Tipfy。
3 个回答
在你现在的情况中,使用OAuth可能有点过于复杂了(可能不安全),因为OAuth的设计目的是为了让第三方服务能够代表用户访问资源。
通过授权用户保护AJAX请求
根据我所了解,你可以控制客户端、资源和身份验证;所以你只需要确保URL的访问安全,可能还需要通过SSL来保护客户端和服务器之间的通信[2]。
因此,可以使用Tipfy的身份验证扩展来保护你的URL:
from tipfy import RequestHandler, Response
from tipfy.ext.auth import AppEngineAuthMixin, user_required
class MyHandler(RequestHandler, AppEngineAuthMixin):
@user_required
def get(self, **kwargs):
return Response('Only logged in users can see this page.')
没有授权用户的情况下保护AJAX请求
如果用户是未知的,那么可以采取一些措施来防止CSRF攻击,以保护REST服务不被“未授权”的客户端调用。Tipfy在它的WTForms扩展中内置了这个功能,但它不是AJAX的。相反,可以使用会话扩展为所有请求添加一个“authenticity_token”,这个token需要在服务器上进行验证。
保护一个JavaScript客户端几乎是不可能的。在服务器端,你没有办法百分之百区分是人类在用浏览器,还是一个精心制作的脚本在操作。
SSL可以加密数据在传输过程中,但在到达目的地时会解密,所以这并不能解决问题。它可以防止中间人攻击,但对验证原始客户端的合法性没有帮助。
OAuth在两个服务器之间的请求安全性上表现不错,但对于JavaScript客户端来说,帮助不大:任何人只要查看你的JavaScript代码,就能找到你的消费者密钥和秘密,然后他们就可以伪造签名请求。
不过,有一些方法可以减轻API被抓取的风险:
- 当有人访问你的网站时,生成短期有效的会话cookie。调用REST API时需要有效的会话cookie。
- 生成短期有效的请求令牌,并将其包含在你网站的HTML中;每个API请求都需要有效的请求令牌。
- 要求你网站的用户登录(比如使用Google账户或OpenID);在处理API请求之前检查认证cookie。
- 限制API请求的频率。如果在短时间内从同一个客户端收到过多请求,就阻止他们。
一定要看看 OAuth。
它正在迅速成为保护REST API的“事实标准”,很多大公司都在使用它,比如 谷歌、推特 和 脸书,这些只是其中的一些例子。
在GAE上使用Python,你有两个选择:
我认为最简单的方法是使用David Larlet为 Django提供的OAuth支持库,这个库可以在BitBucket上找到。
不过,因为你不使用Django,或许你想看看在GitHub上可以找到的 python-oauth2库,这个库被认为是Python 2.4+中最新和经过单元测试的OAuth实现。
无论如何,我觉得使用OAuth会比自己开发一个服务安全解决方案要好得多。