是否可以在 HTTP 消息中包含多个授权标头?具体来说,我想包括一种承载令牌类型(传递 OAuth 访问令牌)和一种基本类型(传递 base64 编码的用户名:密码)。
GET /presence/alice HTTP/1.1
Host: server.example.com
Authorization: Bearer mF_9.B5f-4.1JqM
Authorization: Basic YXNkZnNhZGZzYWRmOlZLdDVOMVhk
我认为没有理由这是不可能的,只是想与社区一起审查以确定。
**** 2021 年 2 月更新 *** 请阅读对此回复的评论。他们的总体结论似乎是某些 Web 服务器接受多种授权方案,但这违反了 RFC 7230/7235 ****
这应该是可能的,您只需在字段值之间添加逗号即可,例如:
GET /presence/alice HTTP/1.1
Host: server.example.com
Authorization: Bearer mF_9.B5f-4.1JqM, Basic YXNkZnNhZGZzYWRmOlZLdDVOMVhk
这在 RFC7230,第 3.2.2 节,字段顺序中定义:
发送方不得在消息中生成具有相同字段名称的多个标头字段,除非该标头字段的整个字段值被定义为逗号分隔列表[即#(values)]或者标头字段是一个井-已知异常(如下所述)。
接收者可以将具有相同字段名称的多个头字段组合成一个“字段名称:字段值”对,而不改变消息的语义,方法是将每个后续字段值按顺序附加到组合字段值上,用一个逗号。因此,具有相同字段名称的标头字段的接收顺序对于组合字段值的解释非常重要;代理在转发消息时不得更改这些字段值的顺序。
我不知道是否所有网络服务器都接受这一点 - 在撰写本文时,我正在与一位同事争论它是否应该起作用。
不,这是不可能的。请参阅 http://greenbytes.de/tech/webdav/rfc7235.html#header.authorization
中的语法定义如果你在后端使用 python,那么你可以简单地在 bearer 中传递 dict,然后在后端处理它之前执行 json.loads
通过这种方式,您可以在一个授权标头中传递多个值
示例:通过
{"access_token" : access_token, "app_id" : 2}
后端
json.loads("{"access_token" : access_token, "app_id" : 2}")
标题字段是键/值对。因此,只要它们是独一无二的,并且您/程序员知道谁是谁,就可以了。例如:
AuthorizationBearer: Bearer mF_9.B5f-4.1JqM
AuthorizationBasic: Basic YXNkZnNhZGZzYWRmOlZLdDVOMVhk
当我的 Angular 拦截器将
Authorization111: Bearer xyz123
发送到 Node API 时,API 会将令牌值提取为
// you can do more validation here, i.e, length
var token = header.headers["authorization111"].toString().split(' ')[1];
虽然
Authorization
的逗号分隔值在技术上是最佳解决方案,但作为最后的立场,您可以尝试将普通用户凭据作为 URL 的一部分与您选择的 httpClient 一起添加,并使用它发送 Bearer
标头。如果没有其他办法的话可能会起作用:
https://myUsername:[email protected]/presence/alice
由于此处使用明文密码,这只是为了完整性,而不是推荐的方式。
有可能有多个授权标头,我在集成接受多个授权的API时遇到了同样的问题。
这里是 React js 示例,用于调用接受多个身份验证令牌的 API。
axios.get(Constants.API+Constants.GET_USER, { headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
"Authorization": Constants.AUTH_Element + ',' + Constants.AUTH_ORG + ','+
Constants.AUTH_USER
}})
.then(function (response) {
// handle success
console.log(response);
})
.catch(function (error) {
// handle error
console.log(error);
})
.finally(function () {
// always executed
});