自定义 Authorization HTTP 标头

Posted

技术标签:

【中文标题】自定义 Authorization HTTP 标头【英文标题】:Customize the Authorization HTTP header 【发布时间】:2012-01-17 19:50:34 【问题描述】:

当客户端向 API 发送请求时,我需要对其进行身份验证。客户端有一个 API 令牌,我正在考虑使用标准的 Authorization 标头将令牌发送到服务器。

通常此标头用于BasicDigest 身份验证。但我不知道是否允许我自定义此标头的值并使用自定义身份验证方案,例如:

Authorization: Token 1af538baa9045a84c0e889f672baf83ff24

你会推荐这个吗?或者有没有更好的方法来发送令牌?

【问题讨论】:

【参考方案1】:

您可以创建自己的使用 Authorization: 标头的自定义身份验证架构 - 例如,OAuth 就是这样工作的。

作为一般规则,如果服务器或代理不理解标准标头的,它们将不理会它们并忽略它们。它正在创建您自己的标题 keys,这通常会产生意想不到的结果 - 许多代理会删除带有他们不认识的名称的标题。

话虽如此,使用 cookie 来传输令牌可能更好,而不是 Authorization: 标头,原因很简单,cookie 被明确设计为携带自定义值,而 HTTP 的规范是内置的auth 方法并没有真正说明任何一种方式 - 如果您想确切了解它所说的内容,have a look here。

关于这一点的另一点是,许多 HTTP 客户端库都内置了对 Digest 和 Basic auth 的支持,但在尝试在标头字段中设置原始值时可能会使生活变得更加困难,而它们都将为cookie,并且将在其中允许或多或少的任何值。

【讨论】:

很高兴听到这就是 OAuth 的工作原理。我不确定使用 cookie 是否会使客户端实现更简单。除非您的客户端是浏览器,否则使用 cookie 的规则(路径、过期等)在客户端中实现起来比记住设置标头字段更复杂。大多数客户端库使设置正确的标头变得相当简单。 @ThomasWatson 虽然我不能在 cookie 范围点上不同意您的观点,但在这里应该无关紧要。 HTTP 身份验证的范围(使用Authorization: 标头)是每个域的。这意味着如果您将 cookie 的域设置为“此域”并将路径设置为“/”,它将具有与 HTTP auth 相同的范围。但是,这完全取决于您 - 但正如 Julian Reschke 指出的那样,您可能不应该定义新的身份验证方案,除非您 feel that you have something of generic use - 可以在另一个应用程序中使用的东西。【参考方案2】:

CROSS ORIGIN 请求的情况下,请阅读以下内容:

我遇到这种情况,一开始我选择使用Authorization Header,后来在遇到以下问题后将其删除。

Authorization 标头被视为自定义标头。因此,如果使用Autorization Header 集进行跨域请求,浏览器首先会发送预检请求。预检请求是 OPTIONS 方法的 HTTP 请求,该请求会从请求中剥离所有参数。您的服务器需要使用具有您的自定义标头(Authorization 标头)的值的 Access-Control-Allow-Headers 标头进行响应。

因此,对于客户端(浏览器)发送的每个请求,浏览器都会发送一个额外的 HTTP 请求(OPTIONS)。这降低了我的 API 的性能。 您应该检查添加它是否会降低您的性能。作为一种解决方法,我在 http 参数中发送令牌,我知道这不是最好的方法,但我不能在性能上妥协。

【讨论】:

我也在考虑在 http 参数中发送我的 sessionID。为什么说这不是最好的方法?似乎它具有针对防火墙剥离标头的鲁棒性优势,以及针对跨源性能下降的优势。它有什么缺点? 缺点只在GET请求的情况下。我必须使用我的Authorization token(敏感数据)为我的应用程序验证用户。出于同样的原因,我们不应该在 GET 中发送敏感数据,我们也不应该在 params 中使用授权令牌。根据 w3 w3.org/Protocols/rfc2616/rfc2616-sec15.html#sec15.1.3“HTTP 协议不应使用基于 GET 的表单提交敏感数据”。 如果您不喜欢标头,可以将令牌存储在 cookie 中。 (不要将令牌与会话 ID 混淆)。请注意,通过 PUT 和 DELETE 无论如何它都会发送 OPTIONS... 请注意,大多数时候您使用服务器端 REST 客户端,而浏览器并不被认为是一个非常好的 REST 客户端。【参考方案3】:

这有点过时了,但可能还有其他人正在寻找相同问题的答案。您应该考虑哪些保护空间对您的 API 有意义。例如,您可能想要识别和验证客户端应用程序对您的 API 的访问,以限制它们对已知的注册客户端应用程序的使用。在这种情况下,您可以使用Basic 身份验证方案,其中客户端标识符作为用户标识,客户端共享密钥作为密码。您不需要专有的身份验证方案,只需清楚地识别客户端用于每个保护空间的身份验证方案。我更喜欢每个保护空间只使用一个,但是 HTTP 标准允许在每个 WWW-Authenticate 标头响应上使用多个身份验证方案,并且在每个响应中允许多个 WWW-Authenticate 标头;这会让 API 客户端混淆使用哪些选项。保持一致和清晰,您的 API 才会被使用。

【讨论】:

【参考方案4】:

我建议不要使用带有自定义方案名称的 HTTP 身份验证。不过,如果您觉得您有一些通用用途,您可以定义一个新方案。详情请见http://greenbytes.de/tech/webdav/draft-ietf-httpbis-p7-auth-latest.html#rfc.section.2.3。

【讨论】:

要链接的文档是 HTTP/1.1 的草稿。我一直在尝试查看最终标准,但找不到任何关于我必须注册自定义方案的信息。难道这不仅仅是因为在起草过程中,他们想找到并就默认方案达成一致吗? Thomas,我引用的文档是 RFC 2616/7 的修订版(它没有方案注册表)。它正在进行中,但即将完成。【参考方案5】:

请在下面尝试邮递员:-

在标题部分示例对我有用..

授权:JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyIkX18iOnsic3RyaWN0TW9kZSI6dHJ1ZSwiZ2V0dGVycyI6e30sIndhc1BvcHVsYXRlZCI6ZmFsc2UsImFjdGl2ZVBhdGhzIjp7InBhdGhzIjp7InBhc3N3b3JkIjoiaW5pdCIsImVtYWlsIjoiaW5pdCIsIl9fdiI6ImluaXQiLCJfaWQiOiJpbml0In0sInN0YXRlcyI6eyJpZ25vcmUiOnt9LCJkZWZhdWx0Ijp7fSwiaW5pdCI6eyJfX3YiOnRydWUsInBhc3N3b3JkIjp0cnVlLCJlbWFpbCI6dHJ1ZSwiX2lkIjp0cnVlfSwibW9kaWZ5Ijp7fSwicmVxdWlyZSI6e319LCJzdGF0ZU5hbWVzIjpbInJlcXVpcmUiLCJtb2RpZnkiLCJpbml0IiwiZGVmYXVsdCIsImlnbm9yZSJdfSwiZW1pdHRlciI6eyJkb21haW4iOm51bGwsIl9ldmVudHMiOnt9LCJfZXZlbnRzQ291bnQiOjAsIl9tYXhMaXN0ZW5lcnMiOjB9fSwiaXNOZXciOmZhbHNlLCJfZG9jIjp7Il9fdiI6MCwicGFzc3dvcmQiOiIkMmEkMTAkdTAybWNnWHFjWVQvdE41MlkzZ2l3dVROd3ZMWW9ZTlFXejlUcThyaDIwR09IMlhHY3haZWUiLCJlbWFpbCI6Im1hZGFuLmRhbGUxQGdtYWlsLmNvbSIsIl9pZCI6IjU5MjEzYzYyYWM2ODZlMGMyNzI2MjgzMiJ9LCJfcHJlcyI6eyIkX19vcmlnaW5hbF9zYXZlIjpbbnVsbCxudWxsLG51bGxdLCIkX19vcmlnaW5hbF92YWxpZGF0ZSI6W251bGxdLCIkX19vcmlnaW5hbF9yZW1vdmUiOltudWxsXX0sIl9wb3N0cyI6eyIkX19vcmlnaW5hbF9zYXZlIjp bXSwiJF9fb3JpZ2luYWxfdmFsaWRhdGUIiOltdLCIkX19vcmlnaW5hbF9yZW1vdmUiOltdfSwiaWF0IjoxNDk1MzUwNzA5LCJleHAiOjE0OTUzNjA3ODl9.BkyB0LjKB4FIsCtnM5FcpcBLvKed_j7rCCxZpdwi>

【讨论】:

您真的在 JWT 中发送密码/哈希吗?它是一个简单的 base64。 @Zakhar:SPA 非常典型的做法是将整个用户会话封装在 JWT 中(因为它是一个完整的 json 文档),从而无需在服务器端存储会话。 @cowbert:我不确定在 JWT 中封装比某种会话令牌更多的东西是否是典型的(参见例如this post)。 @AlexanderAbakumov 那篇充满误导性的文章,他得到了一些观点,但他的很多观点没有意义,其中一些他只是无缘无故地反对,我可以说他只是喜欢饼干和我认为他需要从 Bakery 获得一些并修复他的文章,我遇到了很多我使用 cookie 并浪费了几天工作的情况,JWT 和 localStorage 为我节省了很多头痛和时间,这只是 2 个小时的工作和砰,再也不要光顾了。我想知道他是否曾经开发过移动应用程序,尝试过安全规则受到严格限制的浏览器等等。 @Al-Mothafar:如果您以某种方式扩展您的声明,例如 that article full of misleadingsa lot of his points does not make sense 等,我将不胜感激(意思是,这可能超出了此处的评论)。也许您可以写一个答案或博客文章?比较论点会很有趣。

以上是关于自定义 Authorization HTTP 标头的主要内容,如果未能解决你的问题,请参考以下文章

如何在自定义授权方 AWS lambda 函数中访问 http 标头

使用自定义标头获取请求失败

在 IE10 的 AJAX CORS 请求中添加自定义标头时,CORS 请求中止

我应该对 API 密钥使用 Authorization 标头吗

如何为Web请求指定标头

从自定义标头中检索访问令牌