我有一些代码(它实际上用于通过 Web 界面发送 SMS 消息,但这不相关)。该代码在代理服务器不存在的情况下工作正常,但一位客户想要使用此配置。我一直在测试我们的代理,但无法正常工作。在搜索帮助时,我找到了 MSKB 文章 195650(How To Handle Proxy Authorization with WinInet),其中包含了这颗智慧之珠:
There are several ways to handle HTTP_STATUS_PROXY_AUTH_REQ without
displaying a user interface. By far the easiest way to do this is by
using the InternetSetOption function with the flags
INTERNET_OPTION_PROXY_PASSWORD and INTERNET_OPTION_PROXY_USERNAME...
...The same functionality can be accomplished in an MFC application
by detecting HTTP_STATUS_PROXY_AUTH_REQ, calling
CHttpConnection::SetOption, then re-calling CHttpFile::SendRequest.
所以我在我的代码中实现了这个解决方案,检测来自需要身份验证的代理的 407 错误,然后通过 SetOption 调用提供基本身份验证:
if (AfxParseURL (m_csServerUrl, dwServiceType, csServerName, csObjectName, nPort))
{
CString csProxy = m_pOwner->GetProxyServerSetting();
if (csProxy.GetLength() > 0)
{
pSession = new CMyInternetSession (TEXT("SmGen"),
1,
INTERNET_OPEN_TYPE_PROXY,
csProxy,
NULL,
INTERNET_FLAG_KEEP_CONNECTION);
}
else
{
pSession = new CMyInternetSession (TEXT("SmGen"),
1,
INTERNET_OPEN_TYPE_PRECONFIG,
NULL,
NULL,
0);
}
if (pSession)
{
pSession->SetOwnerDialog (m_pOwner);
pHttpConn = pSession->GetHttpConnection (csServerName, (INTERNET_PORT)nPort, NULL, NULL);
if (pHttpConn)
{
dwFlags = INTERNET_FLAG_RELOAD |
INTERNET_FLAG_DONT_CACHE;
pHttpFile = pHttpConn->OpenRequest (CHttpConnection::HTTP_VERB_GET,
csObjectName + TEXT("?") + csHTTP,
NULL,
1,
NULL,
NULL,
dwFlags);
if (pHttpFile)
{
pHttpFile->AddRequestHeaders (csHeaders);
if (pHttpFile->SendRequest ())
{
pHttpFile->QueryInfoStatusCode (dwResult);
bRetryWithAuth = FALSE;
switch (dwResult)
{
case HTTP_STATUS_OK:
// log success
break;
case HTTP_STATUS_PROXY_AUTH_REQ:
bRetryWithAuth = TRUE;
break;
default:
// log failure
break;
}
if (bRetryWithAuth)
{
csProxyUsr = m_pOwner->GetProxyUsername();
csProxyPwd = m_pOwner->GetProxyPassword();
pHttpConn->SetOption (INTERNET_OPTION_PROXY_USERNAME,
csProxyUsr.GetBuffer(1),
csProxyUsr.GetLength());
csProxyUsr.ReleaseBuffer();
pHttpConn->SetOption (INTERNET_OPTION_PROXY_PASSWORD,
csProxyPwd.GetBuffer(1),
csProxyPwd.GetLength());
csProxyPwd.ReleaseBuffer();
if (pHttpFile->SendRequest ())
{
// ... TIMEOUT
现在是问题。问题是第二个 SendRequest 不会失败或引发另一个错误,它只是超时。过了一会儿,我的包装处理程序抛出了 CInternetException 12002(超时)。这有点烦人。不用说,短信永远不会到达。
代理服务器地址的格式为 a.b.c.d:8080 以消除 DNS 的致病因素。我的 MIS 部门向我保证我提供的用户名和密码是有效的(如果我传递了错误的 uid/pwd,它只会恢复为 407 错误,所以我知道他们至少正在访问代理)。
我已经遍历了在这里和网上可以找到的所有内容,但我一无所获。遗憾的是,如果您只有一个代理,那么简单地使用 INTERNET_OPEN_TYPE_PRECONFIG 并希望系统自动获取它需要的一切是行不通的。
请记住,代码的非代理相关功能没有任何问题,因为如果我通过删除提供服务器 ip:port 的注册表项来消除代理,它就会再次出现。
我完全被难住了。有没有人见过这个?鉴于有关代理身份验证的查询数量没有回复,我并不抱希望...
编辑:
我已经将此代码转换为使用 WinHttp,因为有一个 MS 示例涵盖了代理(带身份验证),并且 WinInet 无论如何都被弃用了。现在一切正常。
最佳答案
通常在客户端收到响应后关闭 HTTP 连接。 因此,当您发送带有身份验证详细信息的第二个请求时,代理将关闭连接(或至少停止接收)。
因此您必须再次调用 OpenRequest 以建立新连接。
关于c++ - MFC + Wininet + 代理身份验证 = 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6862189/