将API密钥放在标头或URL中

114
我正在设计一家公司数据的公共 API。我们希望应用程序开发人员注册 API 密钥,以便我们可以监控使用情况和超额使用情况。
由于 API 是 RESTful 的,我的初步想法是将此密钥放入自定义头中。这就是我看到谷歌、亚马逊和雅虎这样做的方式。然而,我的老板认为,如果把密钥作为 URL 的一部分,http://api.domain.tld/longapikey1234/resource之类的,API 就更容易使用了。我猜这种做法确实有它的好处,但它违反了 URL 作为简单地址表示您想要什么的原则,而不是如何或为什么需要它。
您认为把密钥放在 URL 中是否合理?还是您不想在编写简单的 JavaScript 前端代码时手动设置 HTTP 标头呢?
6个回答

103

8
@Thomas:在身份验证头部中放置参数的数量没有限制。看看OAuth,它在头部中有大约8个不同的参数值。 - Darrel Miller
1
链接更新 - 自2014年6月起,此链接现已更新为RFC 7235 - Stephen P
1
我不是说你错了,但当你说“应该是”时,你怎么知道?谁说的?(我发现这个问题是因为Apache在PHP开始执行之前经常会剥离授权头) - JAAulde
2
@JAAulde 我在这里提供更多详细信息 http://www.bizcoder.com/where-oh-where-does-the-api-key-go 如果你有任何关于Apache问题的链接,我会很感兴趣。 - Darrel Miller
@DarrelMiller 谢谢你提供的链接。我同意将其放在头部比URL查询字符串(或伪路径等)中更好,但我希望有某种权威机构能够明确指出应该使用哪个标头。目前我的Apache问题只是个案例,所以我没有任何链接可以回报。我现在倾向于使用类似 X-API-KEY 的东西。 - JAAulde
显示剩余4条评论

81
如果您需要向老板提出说服的论据,请考虑URL是什么。URL是公共的,人们可以复制和粘贴它们,分享它们,并将它们放在广告上。没有任何防止某个人(无论是有意还是无意)将该URL通过电子邮件发送给其他人使用。如果您的API密钥在该URL中,那么每个人都可以使用它。

2
除了您提到的公开披露URL的观点外,URL和内联API密钥将对所有具有路由器、企业代理服务器、缓存服务器等访问权限的网络管理员可见。 - Adam Caviness
5
不涉及HTTPS的情况下,所有API都应该实现HTTP。URL已经加密。作为管理员,您只能查看DNS查询和通信的IP地址,而无法查看内容。除此之外,我同意立场。 - nickdnk
2
@nickdnk,没错。现在关于HTTPS,即使是这样,完整的URL仍然会留在浏览器历史记录中!有趣的事情。我不喜欢任何敏感信息出现在URL中。 - Adam Caviness
@AdamCaviness 是的,在那个意义上。我的理解是,如果有人可以访问路由器,他们就可以读取流量。 - nickdnk
这个API是一个很好的例子,说明了如何不做HTTP。http://pipedrive.com/en/api。 - John John Pichler
URL 中的 API 密钥也意味着它可能出现在各种日志中。 - Craig

24

最好在标头中使用API密钥,而不是在URL中使用。

如果从浏览器尝试,则URL将保存在浏览器历史记录中。这是一个非常罕见的情况。但问题在于后端服务器记录所有URL时可能会暴露API密钥。

有两种方式可以在标头中使用API密钥:

基本授权:

stripe的示例:

curl https://api.stripe.com/v1/charges -u sk_test_BQokikJOvBiI2HlWgH4olfQ2:

curl 使用 -u 标志来传递基本认证凭据(在 API 密钥后添加冒号将防止它要求输入密码)。

自定义标头

curl -H "X-API-KEY: 6fa741de1bdd1d91830ba" https://api.mydomain.com/v1/users

3
为什么要用 X-API-KEY?这个 X 是一种自定义头部的 HTTP 规范吗? - John John Pichler
4
https://dev59.com/CXA65IYBdhLWcg3w7DT8 - Fizer Khan

2

在参数中传递API密钥会使客户难以保密,他们往往会定期泄露密钥。更好的方法是将其传递到请求URL的标头中。您可以在代码中设置用户密钥标头。为了测试您的请求URL,您可以使用Google Chrome中的Postman应用程序,并将用户密钥标头设置为您的API密钥。


4
API密钥在参数中如何导致用户泄露其密钥? - Heinzlmaen
服务器日志以及第七层代理可以记录 URL 到纯文本平面文件中。您可能会认为它们也可以记录标头,但与 URL 相比,这不太常见。除此之外,我想不到任何原因可以解释标头泄露的可能性小于 URL - 否则在所有方面它们都是相等的... - Ashwin Prabhu

1
我不会把密钥放在URL中,因为这违反了REST的松散“标准”。但是,如果你真的要这样做,我会把它放在URL的“用户”部分。
例如:http://me@example.com/myresource/myid 这样可以将其作为基本身份验证的头信息传递。

5
注1) 这只是基本身份验证的简写,2) 并非所有HTTP客户端都会支持它,3) 至少有一个主要的浏览器会显示钓鱼警告。 - user359996
@user359996 已经注意到了。回应如下:1)我在最后一句中已经提到了这一点,2)这在标准中已经提到了(http://tools.ietf.org/html/rfc3986),所以这是客户端的问题,3)我不知道这一点,虽然我认为这是有道理的,但我想知道当它被用作api调用(XHR)时是否仍然是这种情况。最后,问题是关于以restful方式在url中包含auth-info,我认为我已经回答了这个问题。 - Adam Wagner

0
这取决于数据。
如果用户提供数据,请将其放在URL中。
如果您提供数据,请将其放在标头中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接