使用 C# 和 C++ 获取重定向信息

发布于 2024-08-24 12:49:32 字数 5609 浏览 6 评论 0原文


我做错了什么?我正在尝试从用于验证用户身份的服务器获取重定向信息。这适用于我的 C# 代码,但我无法使我的 C++ 代码正常工作。
这是有效的 C# 代码:

string postData = @"username=myUsername&serviceID=someServiceId&password=somePassword";
byte[] postBytes = Encoding.UTF8.GetBytes(postData);

// create the proper HttpWebRequest
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(@"https://myAuthServer.com/login");

request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.Accept = "utf-8";
request.ContentLength = postBytes.Length;
request.PreAuthenticate = true;
request.AllowAutoRedirect = false;

// now get the information from the login server
Stream requestStream = request.GetRequestStream();
HttpWebResponse response = null;

// post the data
requestStream.Write(postBytes, 0, postBytes.Length);

// get the response and get the wanted information
response = (HttpWebResponse)request.GetResponse();

const string Session = "?session=";

Uri location = new Uri(response.Headers["Location"]);
m_redirect = location.Host + location.LocalPath;
m_authentificationId = location.Query.Substring(Session.Length);

我使用这些信息进行进一步的身份验证。一切都很好。

我现在想对 C++ 代码做同样的事情。但该代码不起作用。
所以这里是:

HINTERNET hOpen, hConnect, hReq;
hOpen = InternetOpen(_T(""), INTERNET_OPEN_TYPE_DIRECT, _T(""), _T(""), 0);
if(!InternetHandleValid(hOpen))
{
    return false;
}

hConnect = InternetConnect(hOpen, _T("myAuthServer.com"),
    INTERNET_DEFAULT_HTTPS_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
if(!InternetHandleValid(hConnect))
{
    return false;
}

hReq = HttpOpenRequest(hConnect, _T("POST"), _T("/login"), NULL, NULL,
    NULL, INTERNET_FLAG_NO_AUTO_REDIRECT | INTERNET_FLAG_SECURE, 0);

if(!InternetHandleValid(hReq))
{
    return false;
}

if (!HttpAddRequestHeaders(hReq, _T("Content-Type: application/x-www-form-urlencoded"), -1L, HTTP_ADDREQ_FLAG_ADD))
{
    return false;
}

if (!HttpAddRequestHeaders(hReq, _T("Expect: 100-continue"), -1L, HTTP_ADDREQ_FLAG_ADD))
{
    return false;
}

if (!HttpAddRequestHeaders(hReq, _T("Connection: Keep-Alive"), -1L, HTTP_ADDREQ_FLAG_ADD))
{
    return false;
}

if (!HttpAddRequestHeaders(hReq, _T("Accept: utf-8"), -1L, HTTP_ADDREQ_FLAG_ADD))
{
    return false;
}

CString cstrPostData = _T("username=myUsername&serviceID=someServiceId&password=somePassword");

char buffer[10];
_itoa_s(cstrPostData.GetLength(), buffer, 10, 10);
CString cstrContentLength(buffer);

if (!HttpAddRequestHeaders(hReq, _T("Content-Length: ") + cstrContentLength, -1L, HTTP_ADDREQ_FLAG_ADD))
{
    return false;
}

LPVOID lpData = (LPVOID)cstrPostData.GetBuffer(cstrPostData.GetLength());
if(HttpSendRequest(hReq, NULL, -1L, lpData, wcslen(cstrPostData)))
{
    DWORD dwCode, dwCodeSize; 
    dwCodeSize = sizeof(DWORD);
    if(!HttpQueryInfo(hReq, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &dwCode, &dwCodeSize, NULL))
    {
        return false;
    }

    // we need to have the 302 (Redirect) here
    if (dwCode != 302)
    {
        return false;
    }

    wchar_t chData[1024] = _T("\0");
    DWORD dwBuffer = 1023;
    if(!HttpQueryInfo(hReq, HTTP_QUERY_RAW_HEADERS_CRLF, (LPVOID)chData, &dwBuffer, NULL))
    {
        return false;
    }

    CStringA cstrHeaders(chData);
    bool b = ExtractRedirectAndSessionFromHeader(cstrHeaders);
}

现在的问题是我得到 Location: https://myAuthServer.com/centrallogin-2.2/error.jsp 所以没有正确的重定向和会话。我已经发现,当我没有正确设置 request.ContentType 时,我的 C# 代码中也会出现此错误。但我确实在 C++ 代码中设置了 Content-Type 标头。所以我不知道我做错了什么。
还有什么进一步的想法吗?
编辑:
好的,我也用 WinHTTP API 尝试过。这是我的代码:

HINTERNET hSession = NULL, hConnect = NULL, hRequest = NULL;

// Use WinHttpOpen to obtain a session handle.
hSession = WinHttpOpen(NULL, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME,
    WINHTTP_NO_PROXY_BYPASS, 0);

hConnect = WinHttpConnect(hSession, L"myAuthServer.com", INTERNET_DEFAULT_HTTPS_PORT, 0);
hRequest = WinHttpOpenRequest(hConnect, L"POST", L"/login", NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE);

// disable auto redirects
DWORD dwOptionValue = WINHTTP_DISABLE_REDIRECTS;
BOOL b = WinHttpSetOption(hRequest, WINHTTP_OPTION_DISABLE_FEATURE, &dwOptionValue, sizeof(dwOptionValue));

static const WCHAR szContentType[] = L"Content-Type: application/x-www-form-urlencoded\r\n";
b = WinHttpAddRequestHeaders(hRequest, szContentType, (DWORD)-1, WINHTTP_ADDREQ_FLAG_ADD & WINHTTP_ADDREQ_FLAG_REPLACE);

CString cstrPostData = _T("username=myUsername&serviceID=someServiceId&password=somePassword");
b = WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, -1L, WINHTTP_NO_REQUEST_DATA, 0, wcslen(cstrPostData), 0);

DWORD dwBytesWritten = 0;
b = WinHttpWriteData(hRequest, cstrPostData, wcslen(cstrPostData), &dwBytesWritten);

b = WinHttpReceiveResponse(hRequest, NULL);

DWORD dwSize = sizeof(DWORD);
DWORD dwStatusCode = 0;
b = WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &dwStatusCode,
    &dwSize, WINHTTP_NO_HEADER_INDEX);

wchar_t chData[1024] = _T("\0");
DWORD dwBuffer = 1023; 
b = WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, (LPVOID)chData, &dwBuffer, NULL);
CStringA cstrHeaders(chData);

WinHttpCloseHandle(hSession);
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hRequest);

cstrPostData.ReleaseBuffer();

所以重定向 url 和会话 id 应该在 chData 中。但结果又是错误的。我也尝试过 Wireshark。由于这一切都是 HTTPS,我无法从中读取太多内容。我唯一可以比较的是帧数等。使用 WinHTTP 时,Wireshark 日志看起来很相似。所以我认为这是更好的方法。
还有什么进一步的想法吗?

What am I doing wrong? I'm trying to get redirect information from a server that I use for authenticating a user. This works good with my C# code but I cannot make my C++ code working.

So here's the working C# code:

string postData = @"username=myUsername&serviceID=someServiceId&password=somePassword";
byte[] postBytes = Encoding.UTF8.GetBytes(postData);

// create the proper HttpWebRequest
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(@"https://myAuthServer.com/login");

request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.Accept = "utf-8";
request.ContentLength = postBytes.Length;
request.PreAuthenticate = true;
request.AllowAutoRedirect = false;

// now get the information from the login server
Stream requestStream = request.GetRequestStream();
HttpWebResponse response = null;

// post the data
requestStream.Write(postBytes, 0, postBytes.Length);

// get the response and get the wanted information
response = (HttpWebResponse)request.GetResponse();

const string Session = "?session=";

Uri location = new Uri(response.Headers["Location"]);
m_redirect = location.Host + location.LocalPath;
m_authentificationId = location.Query.Substring(Session.Length);

I use these information for further authentification. Everything is fine.

I now want to do the same with C++ code. But that code doesn't work.

So here is:

HINTERNET hOpen, hConnect, hReq;
hOpen = InternetOpen(_T(""), INTERNET_OPEN_TYPE_DIRECT, _T(""), _T(""), 0);
if(!InternetHandleValid(hOpen))
{
    return false;
}

hConnect = InternetConnect(hOpen, _T("myAuthServer.com"),
    INTERNET_DEFAULT_HTTPS_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
if(!InternetHandleValid(hConnect))
{
    return false;
}

hReq = HttpOpenRequest(hConnect, _T("POST"), _T("/login"), NULL, NULL,
    NULL, INTERNET_FLAG_NO_AUTO_REDIRECT | INTERNET_FLAG_SECURE, 0);

if(!InternetHandleValid(hReq))
{
    return false;
}

if (!HttpAddRequestHeaders(hReq, _T("Content-Type: application/x-www-form-urlencoded"), -1L, HTTP_ADDREQ_FLAG_ADD))
{
    return false;
}

if (!HttpAddRequestHeaders(hReq, _T("Expect: 100-continue"), -1L, HTTP_ADDREQ_FLAG_ADD))
{
    return false;
}

if (!HttpAddRequestHeaders(hReq, _T("Connection: Keep-Alive"), -1L, HTTP_ADDREQ_FLAG_ADD))
{
    return false;
}

if (!HttpAddRequestHeaders(hReq, _T("Accept: utf-8"), -1L, HTTP_ADDREQ_FLAG_ADD))
{
    return false;
}

CString cstrPostData = _T("username=myUsername&serviceID=someServiceId&password=somePassword");

char buffer[10];
_itoa_s(cstrPostData.GetLength(), buffer, 10, 10);
CString cstrContentLength(buffer);

if (!HttpAddRequestHeaders(hReq, _T("Content-Length: ") + cstrContentLength, -1L, HTTP_ADDREQ_FLAG_ADD))
{
    return false;
}

LPVOID lpData = (LPVOID)cstrPostData.GetBuffer(cstrPostData.GetLength());
if(HttpSendRequest(hReq, NULL, -1L, lpData, wcslen(cstrPostData)))
{
    DWORD dwCode, dwCodeSize; 
    dwCodeSize = sizeof(DWORD);
    if(!HttpQueryInfo(hReq, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &dwCode, &dwCodeSize, NULL))
    {
        return false;
    }

    // we need to have the 302 (Redirect) here
    if (dwCode != 302)
    {
        return false;
    }

    wchar_t chData[1024] = _T("\0");
    DWORD dwBuffer = 1023;
    if(!HttpQueryInfo(hReq, HTTP_QUERY_RAW_HEADERS_CRLF, (LPVOID)chData, &dwBuffer, NULL))
    {
        return false;
    }

    CStringA cstrHeaders(chData);
    bool b = ExtractRedirectAndSessionFromHeader(cstrHeaders);
}

Problem now is that I get Location: https://myAuthServer.com/centrallogin-2.2/error.jsp so no proper redirect and session. I already found out that I also get this error in my C# code when I don't set request.ContentType properly. But I did set the Content-Type header in my C++ code. So I have no idea what I do wrong.

Any further ideas?

EDIT:

Ok, I also tried it with the WinHTTP API. Here's my code:

HINTERNET hSession = NULL, hConnect = NULL, hRequest = NULL;

// Use WinHttpOpen to obtain a session handle.
hSession = WinHttpOpen(NULL, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME,
    WINHTTP_NO_PROXY_BYPASS, 0);

hConnect = WinHttpConnect(hSession, L"myAuthServer.com", INTERNET_DEFAULT_HTTPS_PORT, 0);
hRequest = WinHttpOpenRequest(hConnect, L"POST", L"/login", NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE);

// disable auto redirects
DWORD dwOptionValue = WINHTTP_DISABLE_REDIRECTS;
BOOL b = WinHttpSetOption(hRequest, WINHTTP_OPTION_DISABLE_FEATURE, &dwOptionValue, sizeof(dwOptionValue));

static const WCHAR szContentType[] = L"Content-Type: application/x-www-form-urlencoded\r\n";
b = WinHttpAddRequestHeaders(hRequest, szContentType, (DWORD)-1, WINHTTP_ADDREQ_FLAG_ADD & WINHTTP_ADDREQ_FLAG_REPLACE);

CString cstrPostData = _T("username=myUsername&serviceID=someServiceId&password=somePassword");
b = WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, -1L, WINHTTP_NO_REQUEST_DATA, 0, wcslen(cstrPostData), 0);

DWORD dwBytesWritten = 0;
b = WinHttpWriteData(hRequest, cstrPostData, wcslen(cstrPostData), &dwBytesWritten);

b = WinHttpReceiveResponse(hRequest, NULL);

DWORD dwSize = sizeof(DWORD);
DWORD dwStatusCode = 0;
b = WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &dwStatusCode,
    &dwSize, WINHTTP_NO_HEADER_INDEX);

wchar_t chData[1024] = _T("\0");
DWORD dwBuffer = 1023; 
b = WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, (LPVOID)chData, &dwBuffer, NULL);
CStringA cstrHeaders(chData);

WinHttpCloseHandle(hSession);
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hRequest);

cstrPostData.ReleaseBuffer();

So the redirect url and the session id should be in chData. But again the result is wrong. I also tried Wireshark. As this all is HTTPS I cannot read much out of it. Only thing I could compare is the number of frames etc. When using WinHTTP the Wireshark log looks similar. So I think this is the better approach.

Any further ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

若言繁花未落 2024-08-31 12:49:33

对此引用MSDN 页面功能:

指向字符串变量的指针
包含要附加到的标头
的请求。每个标头必须是
由 CR/LF 终止(回车
返回/换行)对。

所以你的字符串需要以“\r\n”结尾

To quote from the MSDN page for this function:

Pointer to a string variable
containing the headers to append to
the request. Each header must be
terminated by a CR/LF (carriage
return/line feed) pair.

So your strings need to be terminated with "\r\n"

南街九尾狐 2024-08-31 12:49:33

好吧,我终于修好了。问题是我的发布数据字符串 CString cstrPostData 被解释为 CStringW。所以发送的数据就是问题所在。当我明确地将发布数据字符串更改为 CStringA cstrPostData 时,一切都是正确的。

Ok, I finally fixed it. The problem was that my post data string CString cstrPostData was interpreted as CStringW. So the data that was sent was the problem. When I explicitly changed the post data string to CStringA cstrPostData everything was correct.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文