基本的HTTP和Bearer令牌身份验证

179

我目前正在开发一个REST-API,该API在开发环境下受到HTTP基本身份验证的保护。由于实际认证是通过令牌完成的,我仍在努力弄清楚如何发送两个授权头。

我尝试了这个方法:

curl -i http://dev.myapp.com/api/users \
  -H "Authorization: Basic Ym9zY236Ym9zY28=" \
  -H "Authorization: Bearer mytoken123"

例如,我可以禁用我的IP的HTTP身份验证,但由于我通常在具有动态IP的不同环境中工作,这不是一个好的解决方案。那么,我是否遗漏了什么?


3
我需要通过HTTP基本认证进行身份验证,因为Dev服务器受到了保护,而我需要基于令牌的身份验证来使用API。但是,由于我使用curl测试API,所以我需要一种方式来发送两个身份验证标头。因此,第一个(基本)用于通过HTTP基本认证,第二个(令牌)用于对我的应用程序进行身份验证。是的,这是我自己创建的。 - Azngeek
3
你最近解决这个问题了吗?我会添加一笔悬赏。 - Adam Waite
4
抱歉,Adam您好。现在无法这样做。我已更改认证方式,将授权标头中的令牌更改为“x-auth”,这不是一个标准标头。 - Azngeek
1
我的nginx服务器甚至不接受2个授权头。它返回一个“400 Bad request”的错误。太傻了。 - Rudie
1
使用自定义标头作为API令牌有什么问题吗?我不明白为什么这里的人们放弃了使用HTTP基本身份验证来保护他们的开发/暂存服务器免受窥探。 - Sunil D.
显示剩余4条评论
9个回答

107

尝试使用此方法在URL中推送基本身份验证:

curl -i http://username:password@dev.myapp.com/api/users -H "Authorization: Bearer mytoken123"
               ^^^^^^^^^^^^^^^^^^

如果上述方法无效,那么您就无能为力了。请尝试以下替代方案。

您可以使用另一个名称传递令牌。因为您正在从应用程序处理授权。所以您可以轻松地利用这种灵活性来实现这个特殊目的。

curl -i http://dev.myapp.com/api/users \
  -H "Authorization: Basic Ym9zY236Ym9zY28=" \
  -H "Application-Authorization: mytoken123"

请注意,我已将标头更改为Application-Authorization。因此,请在应用程序中捕获该标头下的令牌,并处理所需操作。

另一件事情是,通过POST参数传递token并从服务器端获取参数值。例如使用curl post参数传递令牌:

-d "auth-token=mytoken123"

1
你好Sabuj,问题不在于您传递用户名和密码的方式,而是多个授权标头无法正常工作。查看规范(https://www.ietf.org/rfc/rfc2617.txt),我可以看到这应该是可能的。但正如所述:“用户代理程序必须选择使用其了解的具有最强身份验证方案之一的挑战,并根据该挑战要求用户提供凭据。”因此,就像我两天前写的那样,当您处理非标准架构时,需要将令牌传递到非标准标头中,这是完全可以的。 - Azngeek
6
Curl在执行任务时会发送两个授权标头。你需要从你的服务器端处理它。只需在curl命令中使用“-v”参数运行,同时附上这两个标头。你会发现它在请求标头中发送了“Authorization: Basic Ym9zY236Ym9zY28=, Authorization: Bearer mytoken123”。如果你从服务器端检查,就会发现你有一个类似于这样的Authorization标头:“Authorization: Basic Ym9zY236Ym9zY28=, Bearer mytoken123”,用逗号分隔开来。所以,我认为我应该给你提供一些替代方法。 - Sabuj Hassan

36

标准(https://www.rfc-editor.org/rfc/rfc6750)规定您可以使用以下内容:

  • 表单编码的Body参数:Authorization: Bearer mytoken123
  • URI查询参数:access_token=mytoken123

因此,使用URI传递许多Bearer Token是可能的,但是这样做是不鼓励的(请参见标准中的第5节)。


在查询参数中添加秘密数据真的是一个很糟糕的主意。 - Vlad

6
如果您在中间使用反向代理,例如 nginx,可以定义自定义令牌,例如 X-API-Token
在 nginx 中,您需要将其重写为上游代理(您的 REST API)只是 auth:
proxy_set_header Authorization $http_x_api_token;

...而nginx可以使用原始的Authorization标头来检查HTTP身份验证。


完美!在找到你的回答之前,我搜索了几个小时。对于任何正在搜索的人,在我的请求中有 X-API-token 头部就行。值应该是“Bearer <token_value>”。 - kanadianDri3

4
使用Nginx,您可以像这样发送两个令牌(尽管这违反了标准):
Authorization: Basic basic-token,Bearer bearer-token

只要基本令牌排在最前面,nginx就能成功将其转发到应用程序服务器。然后你需要确保你的应用程序可以正确从上述字符串中提取Bearer。

3

我曾经遇到过类似的问题——在设备上进行设备和用户认证。我使用一个Cookie头和一个Authorization: Bearer...头。其中一个头用于设备认证,另一个头用于用户认证。我使用Cookie头是因为它们常用于认证。


不清楚为什么会被踩。我在寻找相关问题的答案时遇到了这个问题 - 这就是我解决它的方法。Cookie头已经经常用于身份验证。 - Iiridayn
4
我认为一些人的问题在于,像我一样不知道您发送的cookie是什么——是否与标头相同、仅为一个令牌或其他内容? - René W.

2

curl --anyauth

告诉curl自己找出身份验证方式,并使用远程站点声称支持的最安全的一种。首先执行请求并检查响应头,从而可能引发额外的网络往返。这是用来代替设置特定的身份验证方法的,你可以使用--basic、--digest、--ntlm和--negotiate。


2

在开发服务器上测试API的另一种解决方案是:

  • 仅对Web路由设置HTTP基本身份验证
  • 让所有API路由免于身份验证

NginxLaravel的Web服务器配置如下:

    location /api {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location / {
        try_files $uri $uri/ /index.php?$query_string;

        auth_basic "Enter password";
        auth_basic_user_file /path/to/.htpasswd;
    }

Authorization: Bearer将保护开发服务器免受网络爬虫和其他不必要的访问者攻击。


1
真正的答案是:
  1. 您不能使用相同名称的两个标头(只有一个例外,即Set-Cookie)。
  2. Bearer令牌是一种授权方案,而Basic是一种身份验证方案。
因此,您的问题一开始就存在错误,并且您的应用程序逻辑流程存在问题。
  • 如果您想要将客户端身份验证为特定用户,请在请求中使用基本身份验证方案,此时授权令牌是无用的(用户通过匹配的密钥证明了自己)。
  • 如果您只想确保客户端被授权执行某些操作,请使用无需身份验证的令牌授权(用户提供只有授权人员应该知道的密钥,您信任它而无需进行额外验证)。
在客户端端,您通常不知道用户名/密码和令牌。在最常见的工作流程中,您进行一次身份验证,接收令牌,并在所有后续请求中使用它。此外,令牌可能具有过期时间,应用程序应该在每个响应中指示它,以示基本的礼貌。
简而言之,Bearer令牌授权是您旧有的可靠会话cookie的特殊情况。

1
你可以使用Body和x-www-form-urlencoded一起发送多个头信息。
curl --location --request POST 'http://dev.myapp.com/api/users' \
--header 'Authorization: Basic Ym9zY236Ym9zY28=' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'access_token=mytoken123'

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