我有一个自定义的http组件,它使用Wininet来处理http POST和GET。它工作正常,但有些网站在响应标头中返回一个Set-Cookie
参数,他们希望浏览器在下次调用时使用此cookie。据我所知,我的基于wininet的组件不处理这些cookie。当我使用像Http Analyzer这样的http嗅探器时,我可以看到它。 IE工作正常。我的请求标题中没有任何不同,它与IE创建的相同。
我应该自己处理这些饼干吗?如果是这样,怎么样?
WinInet不处理cookie。你需要自己处理它。
在WinInet图书馆中,你会找到InternetGetCookie()
和InternetSetCookie()
。关于Managing Cookies有一篇很好的MSDN文章。
细节将取决于您的应用程序及其架构,但我通常会发现使用InternetGetCookie()
clunky的实现。相反,我会在调用InternetReadFile()
时检索所有HTTP头,然后在存在cookie时调用InternetSetCookie()
:
// Create a session cookie.
bReturn = InternetSetCookie(TEXT("http://www.adventure_works.com"), NULL,
TEXT("TestData = Test"));
可以找到带有检索HTTP头的示例的MSDN文章here。
上面的答案是错误的。 CInternetSession确实处理cookie。如果此会话下的http响应返回Set-Cookie标头,则其中的cookie将自动由会话对象保存,并在后续请求时返回给服务器。无需使用SetCookie()。
但是有一些注意事项和陷阱:没有过期日期返回的Cookie是会话cookie,只保存在MEMORY中。当CInternetSession对象被销毁时,它们永远消失。
可以使用SetOption和禁用cookie的请求在CInternetSession对象中设置标志。请参阅标志INTERNET_OPTION_SUPPRESS_SERVER_AUTH和INTERNET_FLAG_NO_COOKIES。小心,所以你没有这样做。
小心CACHING。获取一次脚本以获取cookie,然后再次获取它以打印返回的cookie。它不起作用!没有打印cookie。为什么?因为“文件”是缓存的。在第二次调用wininet没有联系服务器,它再次给你旧的响应,当然没有打印任何cookie。为避免这种情况,您必须使用标志INTERNET_FLAG_RELOAD。这就是本质:
int flags = INTERNET_FLAG_RELOAD;
int port = INTERNET_DEFAULT_HTTP_PORT;
CHttpConnection *connection = session.GetHttpConnection("www.example.com", flags, port);
CHttpFile *fil = connection->OpenRequest(CHttpConnection::HTTP_VERB_GET, "cgi-bin/test.pl",
0,1,0, "HTTP/1.1", flags);
fil->SendRequest();
另请注意,如果Cookie由URL http://example.com/cgi-bin/test.pl的脚本设置,则它与URL http://example.com/cgi-bin/相关联,因此将返回到脚本http://example.com/cgi-bin/hello.pl。但是,cookie标头可以改变这种行为。