C++用winhttp实现https访问服务器
??????? 由于項(xiàng)目升級(jí),在數(shù)據(jù)傳輸過(guò)程中需要經(jīng)過(guò)OAuth2.0認(rèn)證,訪問(wèn)服務(wù)器需要https協(xié)議。
??????? 首先,實(shí)現(xiàn)C++代碼訪問(wèn)https 服務(wù)器,實(shí)現(xiàn)Get和post功能,在網(wǎng)上搜索一通,發(fā)現(xiàn)各種各樣的都有,有的很簡(jiǎn)單,有的稍微復(fù)雜。結(jié)果MSDN介紹的比較簡(jiǎn)潔一點(diǎn)
??????? 官方網(wǎng)址:https://docs.microsoft.com/en-us/windows/desktop/WinHttp/ssl-in-winhttp
??????? 網(wǎng)友翻譯:https://blog.csdn.net/edger2heaven/article/details/45664297
??????? 我們的要求還是相對(duì)比較簡(jiǎn)單,OAuth 采用客戶端模式(client credentials)
??????? 參考阮一峰blog
??????? http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html
?
客戶端模式(Client Credentials Grant)指客戶端以自己的名義,而不是以用戶的名義,向"服務(wù)提供商"進(jìn)行認(rèn)證。嚴(yán)格地說(shuō),客戶端模式并不屬于OAuth框架所要解決的問(wèn)題。在這種模式中,用戶直接向客戶端注冊(cè),客戶端以自己的名義要求"服務(wù)提供商"提供服務(wù),其實(shí)不存在授權(quán)問(wèn)題。
它的步驟如下:
(A)客戶端向認(rèn)證服務(wù)器進(jìn)行身份認(rèn)證,并要求一個(gè)訪問(wèn)令牌。
(B)認(rèn)證服務(wù)器確認(rèn)無(wú)誤后,向客戶端提供訪問(wèn)令牌。
A步驟中,客戶端發(fā)出的HTTP請(qǐng)求,包含以下參數(shù):
- granttype:表示授權(quán)類型,此處的值固定為"clientcredentials",必選項(xiàng)。
- scope:表示權(quán)限范圍,可選項(xiàng)。
認(rèn)證服務(wù)器必須以某種方式,驗(yàn)證客戶端身份。
B步驟中,認(rèn)證服務(wù)器向客戶端發(fā)送訪問(wèn)令牌,下面是一個(gè)例子。
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的代碼,代碼有點(diǎn)瑕疵,不能通用于普通項(xiàng)目,但是流程是通用的。
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認(rèn)證需要的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認(rèn)證模式是客戶端模式 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());//接收服務(wù)器返回?cái)?shù)據(jù) 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);}?
總結(jié)
以上是生活随笔為你收集整理的C++用winhttp实现https访问服务器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 假设检验实例(python)
- 下一篇: TYPEC 线缆 维修 miniUSB