所以我正在尝试实现以下场景:
- 应用程序受基本身份验证保护。假设它托管在
app.com
上 - 应用程序前面的HTTP代理也需要身份验证。它托管在
proxy.com
上
因此,用户必须在同一请求中为代理和应用程序提供凭据,因此他有不同的用户名/密码对:一对用于根据应用程序验证自己,另一对用于通过代理验证自己。
在阅读了规范之后,我真的不确定我应该如何实现它。我想做的是:
- 用户在没有任何身份验证的情况下向代理发出HTTP请求
- 代理应答
407 Proxy Authentication Required
,并返回格式为:"Proxy-Authenticate: Basic realm="proxy.com"
的Proxy-Authenticate
报头
问题:此Proxy-Authenticate
标头设置正确吗 - 然后,客户端使用
Proxy-Authorization
报头重试请求,即代理username:password
的Base64表示 - 这一次,代理对请求进行身份验证,但随后应用程序使用
401 Unauthorized
标头进行应答。用户已由代理进行身份验证,但未由应用程序进行身份验证。应用程序像WWW-Authenticate: Basic realm="app.com"
一样向响应添加WWW-Authenticate
报头问题:这个头值是正确的,对吗 - 客户端使用
Proxy-Authorization
标头和值为应用程序的username:password
的Base64表示的Authorization
标头再次重试请求 - 此时,代理成功地对请求进行了身份验证,并将请求转发给对用户进行身份验证的应用程序。客户最终得到了回复
整个工作流程是否正确?
是的,对于您所描述的情况,这看起来是一个有效的工作流,并且这些Authenticate标头的格式似乎是正确的。
值得注意的是,给定的连接可能(尽管不太可能)涉及多个链接在一起的代理,并且每个代理本身都可能需要身份验证。在这种情况下,每个中间代理的客户端自身将获得407 Proxy Authentication Required
消息,并且自身使用Proxy-Authorization
报头重复该请求;Proxy-Authenticate
和Proxy-Authorization
报头是不会从一个服务器传递到下一个服务器的单跳报头,但WWW-Authenticate
和Authorization
是端到端报头,被认为是从客户端到最终服务器,由中介逐字传递。
由于Basic
方案以明文形式发送密码(base64是一种可逆编码),因此它最常用于SSL。这个场景是以不同的方式实现的,因为它希望防止代理看到发送到最终服务器的密码:
- 客户端打开到代理的SSL通道以启动请求,但不是提交常规HTTP请求,而是提交一个特殊的
CONNECT
请求(仍然具有Proxy-Authorization
报头)以打开到远程服务器的TCP隧道 - 然后,客户端继续创建嵌套在第一个通道中的另一个SSL通道,通过该通道传输包括
Authorization
标头的最终HTTP消息
在这种情况下,代理只知道客户端连接到的主机和端口,而不知道通过内部SSL通道传输或接收的内容。此外,嵌套通道的使用允许客户端"查看"代理和服务器的SSL证书,从而允许对两者的身份进行身份验证。