我想实现一个API密钥系统来保护对我的应用程序的API调用。
我认为可行的方式是我每个帐户都有一个私钥/秘密。每个请求都包含时间,帐户ID和哈希(时间+秘密) 然后,服务器可以对来自数据库的用户保密做同样的事情,并根据客户端发送的哈希检查。
这是一种合理的方法吗?它对蛮力攻击持开放态度,但我认为只要秘密很长(即uuid)它就不应该是一个太大的问题......
思考
任何人都可以在同一时间内提交另一个请求并使用哈希值,并且在它完全有效之后接受它,对吗?
答案 0 :(得分:4)
问题在于可以重播nonce + hash。真正的身份验证协议至少需要两条消息:
Server Client
---->challenge --->
<----response------
例如,挑战可能是服务器提供的nonce,客户端的响应将是nonce的密码哈希。
不幸的是,这需要 state ,RESTful协议的整个问题是他们不想要保持状态的麻烦。然而他们想要验证......
所以你真的有三个选择:
选项1:假设问题不存在,并使用无状态“身份验证”协议。这与使用cookie没有什么不同。 nonce + password-hash不比cookie更安全。 Cookies可能被盗等,重播。整个网络现在都受到这些重播攻击的困扰。
选项2:尝试将身份验证协议用于无状态通信方法。在这里,您将让客户端向您发送UTC时间戳而不是nonce。使用时间戳提供有限的防御重放。显然,您的时钟不会与客户端的时钟同步,因此您的服务器将允许任何时间戳在某个误差范围内,并且该误差范围将是身份验证协议的重放余量。请注意,这违反了REST,因为身份验证消息不是幂等的。幂等意味着“可以被攻击者成功重放”。
选项3:不要尝试将身份验证协议绑定到无状态协议上。使用SSL。使用客户端证书。不要让客户端下载字符串,而是让他们生成证书,或者您可以为他们提供密钥对。它们通过SSL进行身份验证,不在REST层中进行身份验证。 SSL有很多“开销”。它不是轻量级的,正是因为它 解决了这些重播问题。
所以在一天结束时,这取决于您对API的访问权限。
答案 1 :(得分:2)
对于仅检索数据(私有数据除外)的API,而不是创建,修改或删除数据, this answer中的选项1 可能就足够了。例如,请参阅Bing Maps REST API和Google Maps Premier web services(此处,Google地图也会使用数字签名对网址进行哈希处理 和一个只有API用户知道的特殊密钥,它同时提供防止修改的保护 URL,显然仍然不提供重播攻击保护)。
事实上,一些检索数据的API不使用API密钥,而是以其他方式限制访问(例如,YouTube API允许在不需要身份验证的情况下检索视频和用户频道上的公开数据,但限制了最近的请求数量。)
API不仅需要选项2和/或3,而且只需检索公开可用的数据,例如,如果它修改用户配置文件,发布内容或访问私人信息:例如,参见{{3} },其中OAuth被提及为一种可能的身份验证方案。
特别是对于选项1,此处的API密钥用于跟踪用户对API的访问,最重要的是,限制这些用户的访问。选项1可能不适用于允许无限制数据访问的API。
(这是一个答案,因为评论太长了。)
答案 2 :(得分:0)
服务器包含:
客户发送:
当客户端调用服务器时,服务器会创建密码哈希的哈希值(它知道自己)+随机字符串(通过调用客户端在GET中给出)eand评估是否匹配哈希(通过调用客户端在GET中给出)
更好的方法是创建一个从(密码散列+ nonce)生成秘密散列的函数,其中“nonce”(随机的东西)也存储在服务器上。然后使用username + password调用服务器一次,返回秘密哈希;然后让后续调用完全取决于用户名+随机字符串+散列(秘密散列+随机字符串),使用与上述相同的方法,但秘密就是当时的密码。 这样,即使你的秘密被拦截和撤销,你的通行证仍然是安全的。
显然,好的哈希算法:没有rot13甚至只有md5是值得怀疑的。