我已经为部分遵循this very good blog post by Riyad Kalla的项目创建了一个简单的RESTful API。现在,我已经阅读了堆栈溢出的几十个类似问题,但我似乎无法找到我的安全问题的答案。保护无会话RESTful API端点
简单地说,我的要求是这样的:
- 客户端有一个公共的API密钥(纯文本,任何人嗅探网络流量或正确地检查代码源访问)
- 客户端发送对服务器的请求,与公众的API密钥
- 该服务器有一个秘密的API密钥(秘密到任何人,但开发者)
- 服务器创建客户端的请求数据组成的HMAC-SHA1散列和秘密API密钥
- 服务器发送相同的客户端的请求,API服务器的请求,但其中所产生的HMAC-SHA1
- 的API服务器查找基于公共API密钥收到
- 在其数据库中的秘密API密钥API服务器重新创建使用作为开发者的服务器相同的数据
- 如果哈希匹配,该请求被认为是有效的,并且通常处理
我担心用我的服务了别人HMAC-SHA1哈希可能获取公共API密钥(通过嗅探网络流量),然后简单地卷曲sam e请求客户最初通过使用AJAX的浏览器直接向开发人员的服务器完成。因此,恶意用户可以被认证为合法用户并使用其他人的秘密API密钥访问API。
我会试着举一个具体的例子。通常我会这样做:
- AJAX a get request to my server。
- 我的服务器用我的API密钥散列我的请求并将它发送到API服务器。
- API服务器验证我的请求并返回有效负载。
但我很害怕,:
- 邪恶博士将嗅出我的公开API密钥。
- Dr. Evil将使用我的公共API密钥向我的服务器发送请求。
- 我的服务器会将Dr. Evil的请求与我的API秘密一起打散并发送给API服务器。
- API服务器验证并返回有效载荷以完成Dr. Evil的恶意计划。
- Dr. Evil笑一个邪恶的笑。
我什么都不知道,或者这只是RESTful API游戏的一部分?
更新:我自愿忽略任何形式的时间戳验证,以保持简单,只关注身份验证问题。
更新2:我已经为该过程添加了一个$_SERVER['HTTP_REFERER']
验证。这里的目标是客户端必须发送一个referrer和请求,并且它必须匹配API侧的数据库中列出的引用者。不幸的是,HTTP引用者很容易伪造。这是另一个安全级别,但仍不完美。
更新3:我已更改我的服务器端代码以将引用链接设置为远程IP地址。这会强制发送到我的服务器的每个请求都要使用秘密API密钥进行散列,最终会使用原始请求IP地址访问API服务器。这个IP然后可以被验证并且请求可以通过。我相信它还有可能伪造$_SERVER['REMOTE_ADDR']
,但它比假冒$_SERVER['HTTP_REFERER']
更复杂...我猜还是不完美。
UPDATE 4:根据这些帖子:How to fake $_SERVER['REMOTE_ADDR'] variable?和https://serverfault.com/questions/90725/are-ip-addresses-trivial-to-forge,伪造的$_SERVER['REMOTE_ADDR']
是可能的,虽然困难。但是,由于您无法控制伪造的网络,因此无法收到来自伪造请求的回复。这个请求可以被成功验证,但是它的回应不会落入恶意的手中。
谢谢。我主动排除时间戳部分以使事情变得简单,因为在我当前的代码中实现并不是什么大事,我应该提到这一点。我不确定我是否正确理解SSL的功能。它是否使交通嗅探不可能?恶意用户仍然可以从JavaScript源代码中窃取它,不是吗?我绝对错过了这里的东西...... –
SSL是传输加密。它使得嗅探更加困难。即使使用API,这也是一个好主意。 – datasage
但是如果恶意用户可以从源头获取公共API密钥,我仍然会遇到同样的问题,对吧? –