Что я делаю неправильно? Я пытаюсь получить перенаправление информации с сервера, который я использую для аутентификации пользователя. Это хорошо работает с моим C# кодом, но я не могу заставить мой код на C++ работать.
Так вот рабочий 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
поэтому нет надлежащего редиректа и сессии. Я уже выяснил, что я также получаю эту ошибку в своем коде C#, если я не правильно установил request.ContentType
. Но я установил заголовок Content-Type в моем коде на C++. Поэтому я понятия не имею, что я делаю неправильно.
Любые идеи?
EDIT:
Хорошо, я также пробовал его с помощью API WinHTTP. Вот мой код:
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-адрес перенаправления и идентификатор сеанса должны быть в chData. Но опять же результат неправильный. Я также попробовал Wireshark. Поскольку это все HTTPS, я не могу много прочесть. Единственное, что я мог бы сравнить, это количество кадров и т. Д. При использовании WinHTTP журнал Wireshark выглядит схожим. Поэтому я считаю, что это лучший подход.
Любые идеи?
Хорошая точка зрения, но не решила мою проблему. –
Вы также можете написать управляемый код, используя управляемый C++, в котором вы можете использовать HttpWebRequest, в котором вы не пытаетесь это сделать? Если вы абсолютно не можете использовать .net, то вы также можете попробовать WinHTTP. Если это не работает, получите трассировку wirehark и сравните запрос/ответ между C# и кодом C. – feroze
@feroze: Я попробовал WinHTTP api, см. Мое редактирование ... –