访问Amazon S3时出现HTTP 407代理身份验证所需错误

7
我已经尝试了一切,但似乎无法解决这个问题,只有一个客户端在公司代理/防火墙后面发生了此问题。我们的Silverlight应用程序连接到Amazon S3以下载/上传一些文档。在仅有的一个客户端上,它返回一个407错误,之后该应用程序无法保存任何东西。
Inner Exception:
 System.ServiceModel.ProtocolException: [UnexpectedHttpResponseCode]
Arguments: 407,Proxy Authentication Required

我们在另一个客户那里遇到了类似的问题,但这更多是CORS问题。为了解决这个问题,我使用了CloudFront来模拟子域名,然后访问S3存储桶,这解决了这个问题。我希望它也可以解决这个客户的问题,但事实并非如此。
我尝试将此代码添加到web.config中,这是很多答案建议的方法。
 <system.net>
      <defaultProxy useDefaultCredentials="true" >
      </defaultProxy>
   </system.net>

我已经阅读了关于如何使用用户名和密码通过代理头传递基本认证的文章,但我不确定这对我们有什么帮助。代理服务器由客户端使用,它需要的任何身份验证都在我们的域之外。

**Additional Information**

银光代码引用了2个服务。其中一个是我们的WCF服务,用于检索应用程序的所有数据。另一个是使用亚马逊Soap API的亚马逊S3服务,其终端节点位于http://s3.amazonaws.com/doc/2006-03-01/AmazonS3.wsdl
如果我进入我们的应用程序并仅使用不对亚马逊S3 api进行任何调用的系统部分,则应用程序可以正常工作。但是,一旦我进入需要调用S3的系统部分,问题就开始出现。有趣的是,对S3的调用很好,我可以正常检索文档,但随后对我们的WCF服务的任何调用都会返回407。
有什么想法吗?
**Update 2**

根据Elliot Nelson的评论,我检查了我们应用程序中用于发出http请求的堆栈。结果发现我们默认使用客户端http来处理http和https请求。以下是我们在App.xaml构造函数中的代码:

  public App()
        {
            Startup += Application_Startup;
            UnhandledException += Application_UnhandledException;

            InitializeComponent();

            WebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);
            WebRequest.RegisterPrefix("https://", WebRequestCreator.ClientHttp);

        }

现在,为了理解clienthttp和browserhttp之间的区别以及何时使用它们。还有切换到browserhttp可能带来的潜在影响/问题。
**Update 3**

有没有一种方法可以请求浏览器以信任模式运行您的浏览器内Silverlight应用程序,这样做是否有助于绕过此问题?

你的S3存储桶是否开启了日志记录?这个客户端发出的请求是否能够到达S3,还是被代理截断了? - chris
3个回答

3
对于像这样的企业网络环境,很可能几乎不能在没有IE中设置的自定义代理设置的情况下进行任何操作, 这通常是由企业政策推动的。为了利用这些代理设置,您需要使用 WebRequestCreator.BrowserHttp,它在进行请求时自动使用浏览器的默认设置。
这两个客户端之间的差异表格可以在Microsoft文档中找到。我猜你可能在使用某些不受 BrowserHttp 支持的东西(也许是设置自定义标头或读取原始响应正文)。
出于安全原因,您无法“询问”浏览器其代理设置并使用它们,因此这是一个棘手的情况。您可以按域指定 Browser vs Client 处理方式,甚至针对特定请求(上面的页面描述了如何做到这一点);在这种情况下,您可以尝试只使用 ClientHttp 进行服务调用,而仅在进行 S3 调用时使用 BrowserHttp,并避免整个问题!
接下来,我建议您尝试该方法;如果不起作用,请尝试全面切换到 BrowserHttp 以便“绕过”代理问题(几乎没有机会应用程序实际上将正常工作,因为您可能仅使用 ClientHttp-only 选项)。
从长远来看,您可能需要考虑对服务进行更改,使其可被 BrowserHttp-only 应用程序使用(这将要求您在请求/响应方面非常基本,但仅使用 BrowserHttp 将保证您可以在几乎任何公司网络中工作)。

啊,这是好消息,所以今天你不需要显式地处理代理。除非你在代码中切换到WebRequestCreator.ClientHttp(而不是BrowserHttp),否则Silverlight应该自动使用IE代理设置。请确保你没有这样做,以防万一。 - Elliot Nelson
如果您可以直接在IE中访问所有服务端点,那么测试一下是有意义的。理论上来说,您的应用程序也应该能够访问这些端点。 - Elliot Nelson
太好了!我更新了我的回答,建议你尝试使用BrowserHttp来处理S3调用,使用ClientHttp来处理服务调用的下一步步骤。 - Elliot Nelson
尝试仅使用浏览器的http协议进行S3调用,但没有成功。 - Abhi.Net
真是个糟糕的事情。使用BrowserHttp来处理所有事情应该完全消除您的代理问题,但可能会限制您的应用程序功能(特别是套接字连接)。长期来看,也许您可以修改应用程序,基本上只使用BrowserHttp(可能还需要服务器代码更改),并告知用户他们必须将您的应用程序列入白名单以解除需要ClientHttp的功能的阻止。 - Elliot Nelson
显示剩余2条评论

2
在受信任模式下运行可能是一个组策略问题,需要他们的AD管理员批准/将您的应用程序列入白名单。我认为你面临的根本问题是代理需要NTLM身份验证,由于某种原因,浏览器拒绝向您的应用程序提供该上下文。证明这是NTLM身份验证问题的一种方法是使用curl进行测试 - 让它通过代理进行请求,然后编码会更容易一些。例如,以下curl将使您通过99%的Windows公司代理(假设代理位于proxy-host.corp:3128):
C:\> curl.exe -v --proxy proxy-host:3128 --proxy-user : --proxy-ntlm https://www.google.com
注意:--proxy-user : 告诉curl使用当前用户会话执行NTLM挑战。
因此,如果您可以让客户端运行它,您至少可以确定NTLM有效,然后只需让应用程序使用默认凭据执行NTLM挑战即可(这些凭据可能或可能不由浏览器会话提供)。

0

由于您描述这是一个Silverlight应用程序,我假设您不能使用经典的浏览器代理故障排除,比如“将浏览器移到公共网络”或“尝试使用其他浏览器”,来隔离问题。

您应该尝试隔离代理服务器,并要求客户使用所需的代理身份验证。

该应用程序正在进行请求,但可能被透明代理截获,或结果可能来自于您认为的Web服务器。

早期,401错误与Web身份验证密切相关,而407则用于代理身份验证。

从架构上看,这种分离是一种便利,Web服务器可以具有Web服务器、代理和反向代理行为。

在您的客户环境中发生的情况是,它正在与目标建立Web连接,但它从某个主机(可能是他们的网络,或者有时是供应商)收到HTTP 407状态。几乎肯定请求不是转发的。您的应用程序所在的HTTP客户端需要提供该主机要求的凭据。公司的环境足够复杂,以至于通常您的客户会说这是他们第一次听说这个问题(某些代理身份验证也是动态的或特定于目的地的)。

此外,在某些企业环境中,操作员将允许从代理身份验证服务进行临时或永久白名单。您应该查看他们是否可以这样做,即使是暂时的,以确认不会出现其他问题。
最终,听起来您的应用程序可能不太支持代理身份验证,或者他们在其环境中使用的代理身份验证类型不太适合。

这绝对是事实,但我在寻找我们可以在我们这边做些什么来解决这个问题。白名单在过去起作用了,但肯定有一种方法可以修改我们的应用程序来处理这个问题。 - Abhi.Net
看看能否找出使用了哪种代理身份验证。这可能是配置问题,也可能是您需要通过支持代理身份验证携带的新凭据类型来扩展应用程序。 - benc
你所说的代理身份验证是指什么类型的?你是指客户端代理基于NTLM还是Kerberos?还是你指的是其他什么东西? - Abhi.Net
是的。当我为Mozilla工作时,有基本认证和NTLM...但我相信技术已经向前发展了... - benc

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