2010-03-05 2 views
0


Что я делаю неправильно? Я пытаюсь получить перенаправление информации с сервера, который я использую для аутентификации пользователя. Это хорошо работает с моим 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 выглядит схожим. Поэтому я считаю, что это лучший подход.
Любые идеи?

ответ

0

Хорошо, я наконец установил ее. Проблема заключалась в том, что моя строка данных CString cstrPostData была переведена как CStringW. Таким образом, данные, которые были отправлены, были проблемой. Когда я явно изменил строку данных post на CStringA cstrPostData, все было правильно.

1

Цитирую the MSDN page для этой функции:

Указатель на строку с переменной , содержащий заголовки для добавления к запроса. Каждый заголовок должен быть , прерванный CR/LF (каретка возвращение/линия) пара.

Так что ваши строки должны заканчиваться «\ г \ п»

+0

Хорошая точка зрения, но не решила мою проблему. –

+1

Вы также можете написать управляемый код, используя управляемый C++, в котором вы можете использовать HttpWebRequest, в котором вы не пытаетесь это сделать? Если вы абсолютно не можете использовать .net, то вы также можете попробовать WinHTTP. Если это не работает, получите трассировку wirehark и сравните запрос/ответ между C# и кодом C. – feroze

+0

@feroze: Я попробовал WinHTTP api, см. Мое редактирование ... –

Смежные вопросы