C++用winhttp实现https访问服务器
??????? 由于項目升級,在數據傳輸過程中需要經過OAuth2.0認證,訪問服務器需要https協議。
??????? 首先,實現C++代碼訪問https 服務器,實現Get和post功能,在網上搜索一通,發現各種各樣的都有,有的很簡單,有的稍微復雜。結果MSDN介紹的比較簡潔一點
??????? 官方網址:https://docs.microsoft.com/en-us/windows/desktop/WinHttp/ssl-in-winhttp
??????? 網友翻譯:https://blog.csdn.net/edger2heaven/article/details/45664297
??????? 我們的要求還是相對比較簡單,OAuth 采用客戶端模式(client credentials)
??????? 參考阮一峰blog
??????? http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html
?
客戶端模式(Client Credentials Grant)指客戶端以自己的名義,而不是以用戶的名義,向"服務提供商"進行認證。嚴格地說,客戶端模式并不屬于OAuth框架所要解決的問題。在這種模式中,用戶直接向客戶端注冊,客戶端以自己的名義要求"服務提供商"提供服務,其實不存在授權問題。
它的步驟如下:
(A)客戶端向認證服務器進行身份認證,并要求一個訪問令牌。
(B)認證服務器確認無誤后,向客戶端提供訪問令牌。
A步驟中,客戶端發出的HTTP請求,包含以下參數:
- granttype:表示授權類型,此處的值固定為"clientcredentials",必選項。
- scope:表示權限范圍,可選項。
認證服務器必須以某種方式,驗證客戶端身份。
B步驟中,認證服務器向客戶端發送訪問令牌,下面是一個例子。
HTTP/1.1 200 OKContent-Type: application/json;charset=UTF-8Cache-Control: no-storePragma: no-cache{"access_token":"2YotnFZFEjr1zCsicMWpAA","token_type":"example","expires_in":3600,"example_parameter":"example_value"}?
以下是POST的代碼,代碼有點瑕疵,不能通用于普通項目,但是流程是通用的。
GET的代碼也是大同小異,只是https頭部信息有所不用
#include "stdafx.h" #include "windows.h" #include "winhttp.h" #include "wchar.h" #include "wincrypt.h" #include <comdef.h>#pragma comment(lib, "Winhttp.lib") #pragma comment(lib, "Crypt32.lib")wstring string2wstring(const string &str) {_bstr_t tmp = str.c_str();wchar_t* pwchar = (wchar_t*)tmp;wstring ret = pwchar;return ret; }void winhttp_client_post(){LPSTR pszData = "WinHttpWriteData Example"; DWORD dwBytesWritten = 0; BOOL bResults = FALSE; HINTERNET hSession = NULL,hConnect = NULL,hRequest = NULL;// Use WinHttpOpen to obtain a session handle. hSession = WinHttpOpen( L"A WinHTTP Example Program/1.0", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);// Specify an HTTP server. if (hSession)hConnect = WinHttpConnect( hSession, L"www.wingtiptoys.com",INTERNET_DEFAULT_HTTPS_PORT, 0);// Create an HTTP Request handle. if (hConnect)hRequest = WinHttpOpenRequest( hConnect, L"POST", L"/token", NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, 0);// Set HTTP Options DWORD dwTimeOut = 3000; DWORD dwFlags =SECURITY_FLAG_IGNORE_UNKNOWN_CA |SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE |SECURITY_FLAG_IGNORE_CERT_CN_INVALID |SECURITY_FLAG_IGNORE_CERT_DATE_INVALID;BOOL bRet = WinHttpSetOption(hRequest, WINHTTP_OPTION_CONNECT_TIMEOUT, &dwTimeOut, sizeof(DWORD)); bRet = WinHttpSetOption(hRequest, WINHTTP_OPTION_SECURITY_FLAGS, &dwFlags, sizeof(dwFlags)); bRet = WinHttpSetOption(hRequest, WINHTTP_OPTION_CLIENT_CERT_CONTEXT, WINHTTP_NO_CLIENT_CERT_CONTEXT, 0);//加上OAuth認證需要的header信息: std::string client_id = "test client id"; std::string client_secure = "test client security"; // client id and secure need base64 encode std::wstring strHeader = L"Content-type:application/x-www-form-urlencoded\r\n"; strHeader += L"Authorization: Basic "; //strHeader += string2wstring(tmsstring) +L"\r\n"; //tmsstring is client and secure after base64 encodingbRet = WinHttpAddRequestHeader(hRequest, strHeader.c_str(), strHeader.length(), WINHTTP_ADDREQ_FLAG_ADD|WINHTTP_ADDREQ_FLAG_REPLACE); // Send a Request.std::string strTmp = "grant_type=client_credentials"; //OAuth認證模式是客戶端模式 if (hRequest) bResults = WinHttpSendRequest( hRequest, WINHTTP_NO_ADDITIONAL_HEADERS,0, (LPVOID)strTmp.c_str(), strTmp.length(), strTmp.length(), 0);// Write data to the server. don't need this step /*if (bResults)bResults = WinHttpWriteData( hRequest, pszData, (DWORD)strlen(pszData), &dwBytesWritten); */ // End the request. if (bResults)bResults = WinHttpReceiveResponse( hRequest, NULL);// Report any errors. if (!bResults)printf("Error %d has occurred.\n",GetLastError());//接收服務器返回數據 if(bRet) {char *pszOutBuf;DWORD dwSize = 0;DWORD dwDownLoaded = 0;std::string strJson; //返回的是Json格式do{if (!WinHttpQueryDataAvailable(hRequest, &dwSize)){//error log}pszOutBuf = new char[dwSize+1];ZeroMemory(pszOutBuf, dwSize+1);if (!WinHttpReadData( hRequest, (LPVOID)pszOutBuf, dwSize, &dwDownLoaded) ){//error log}strJson += pszOutBuf;}while(dwSize > 0); }// Close any open handles. if (hRequest) WinHttpCloseHandle(hRequest); if (hConnect) WinHttpCloseHandle(hConnect); if (hSession) WinHttpCloseHandle(hSession);}?
總結
以上是生活随笔為你收集整理的C++用winhttp实现https访问服务器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 假设检验实例(python)
- 下一篇: s3c2440移植MQTT