由于项目升级,在数据传输过程中需要经过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请求,包含以下参数:
POST /token HTTP/1.1 Host: server.example.com Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW Content-Type: application/x-www-form-urlencoded grant_type=client_credentials
认证服务器必须以某种方式,验证客户端身份。
B步骤中,认证服务器向客户端发送访问令牌,下面是一个例子。
HTTP/1.1 200 OK Content-Type: application/json;charset=UTF-8 Cache-Control: no-store Pragma: 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
#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 encoding
bRet = 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);
}