2010-03-05 18 views
0


Qu'est-ce que je fais de mal? J'essaie d'obtenir des informations de redirection à partir d'un serveur que j'utilise pour authentifier un utilisateur. Cela fonctionne bien avec mon code C# mais je ne peux pas faire fonctionner mon code C++.
est donc ici le code C# de travail:Obtention d'informations de redirection avec C# et 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); 

J'utilise ces informations pour plus d'authentification. Tout va bien.

Je veux maintenant faire la même chose avec le code C++. Mais ce code ne fonctionne pas.
Voici donc:

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); 
} 

Le problème est maintenant que je reçois Location: https://myAuthServer.com/centrallogin-2.2/error.jsp donc pas redirect et session appropriée. J'ai déjà découvert que je reçois également cette erreur dans mon code C# lorsque je ne définis pas correctement request.ContentType. Mais j'ai défini l'en-tête Content-Type dans mon code C++. Donc je n'ai aucune idée de ce que je fais de mal.
D'autres idées?
EDIT:
Ok, j'ai aussi essayé avec l'API WinHTTP. Voici mon 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(); 

L'URL de redirection et l'ID de session doivent donc être dans chData. Mais encore une fois le résultat est faux. J'ai aussi essayé Wireshark. Comme tout cela est HTTPS, je ne peux pas en lire beaucoup. La seule chose que je pourrais comparer est le nombre d'images, etc. Lorsque vous utilisez WinHTTP, le journal Wireshark est similaire. Donc, je pense que c'est la meilleure approche.
D'autres idées?

Répondre

0

Ok, je enfin le fixe. Le problème était que ma chaîne de données post CString cstrPostData a été interprétée comme CStringW. Donc, les données qui ont été envoyées étaient le problème. Lorsque j'ai explicitement changé la chaîne de données post à CStringA cstrPostData tout était correct.

1

Voici un extrait de the MSDN page pour cette fonction:

pointeur à une variable chaîne contenant les en-têtes à ajouter à la demande. Chaque en-tête doit être terminé par une paire CR/LF (chariot retour/saut de ligne).

donc vos chaînes doivent se terminer par "\ r \ n"

+0

Bon point, mais n'a pas résolu mon problème. –

+1

Vous pouvez également écrire du code managé en utilisant C++ géré, dans lequel vous pouvez utiliser HttpWebRequest, pourquoi ne pas essayer cela? Si vous ne pouvez absolument pas utiliser .net, vous pouvez également essayer avec WinHTTP. Si cela ne fonctionne pas non plus, obtenez une trace wireshark et comparez la requête/réponse entre les codes C# et C. – feroze

+0

@feroze: J'ai essayé l'API WinHTTP, voir mon edit ... –