QT实现一个Https客户端

最近在做基于Https协议的项目编程,以下实现一个基于QT的Https的客户端

1.环境

本QT4.7.0+VS2008+Win10.

2.NetWork类库

QT实现一个Https客户端_第1张图片

  1. 三个类

主要使用了以下三个类:
http访问的类:QNetworkAccessManager
http请求的类:QNetworkRequest
http回复的类:QNetworkReply
使用上面三个类可以实现http客户端所有功能,简单地调用如下:

reply = manager->get(request);
reply = manager->post(request, data);
  1. QNetworkAccessManager

QNetworkAccessManager的调用方法,根据不同的类型可以调用不同的方法:

QNetworkReply *	deleteResource ( const QNetworkRequest & request )
QNetworkReply *	get ( const QNetworkRequest & request )
QNetworkReply *	head ( const QNetworkRequest & request )
QNetworkReply *	post ( const QNetworkRequest & request, QIODevice * data )
QNetworkReply *	post ( const QNetworkRequest & request, const QByteArray & data )
QNetworkReply *	put ( const QNetworkRequest & request, QIODevice * data )
QNetworkReply *	put ( const QNetworkRequest & request, const QByteArray & data )


  1. 请求Url和request
	QNetworkRequest request;
    QUrlQuery urlQuery;
    QString urlString;
    QUrl url;
    
    /* url */
    urlString.append("https://httpbin.org/");
    url.setUrl(urlString);

    /* query */
    urlQuery.addQueryItem("id", "123456");
    urlQuery.addQueryItem("time", "2019-10-01 10:30:00");
    url.setQuery(urlQuery);
    //由于QT4.7.0中不支持QUrlQuery类,所以这里可采用手动拼接方式
    if (!url.contains("?", Qt::CaseInsensitive))
     {
		url.append("?");
	} 
	else 
	{
		url.append("&");
	}
	url.append(Key + "=" + Value);

	//拼接最后如下
	https://www.example.com?key1=value1&key2=value2
	
	//也可以使用QUrl的addQueryItem函数
	//QT4的写法:
	QUrl url("http://www.example.com");
	url.addQueryItem("key1", "value1");
	url.addQueryItem("key2", "value2");
	//QT5的写法
	QUrl url("http://www.example.com");
	QUrlQuery urlQuery(url);
	urlQuery.addQueryItem("key1", "value1");
	urlQuery.addQueryItem("key2", "value2");
	url.setQuery(urlQuery);
	//QT4和QT5的混合写法:
	QUrl url("http://www.example.com");
#if (QT_VERSION <= QT_VERSION_CHECK(5,0,0)) // Qt4
    url.addQueryItem("key1", "value1");
    url.addQueryItem("key2", "value2");
#else
    QUrlQuery urlQuery(url);
    urlQuery.addQueryItem("key1", "value1");
    urlQuery.addQueryItem("key2", "value2");
    url.setQuery(urlQuery);
#endif
	

    request.setUrl(url);
  1. 追加或修改头Head数据

    void QNetworkRequest::setRawHeader ( const QByteArray & headerName, const QByteArray & headerValue )

	QNetworkRequest request;
    request.setRawHeader("User-Agent", "QHttpsC 1.0");
    request.setRawHeader("Authorization", "Basic WHtpsWeeSFW4=");
    request.setRawHeader("Last-Modified", "Sun, 06 Nov 2019 08:49:37 GMT");

  1. 增加body数据,使用Post上传负载数据data
	//QNetworkReply *	post ( const QNetworkRequest & request, const QByteArray & data )
	reply = manager->post(request, data);//data数据可能是Json格式串
  1. 返回数据的读取
  • 读取返回的状态码
/*200  服务器成功返回网页 
404  请求的网页不存在 
503  服务不可用*/
	QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
    int retCode = statusCode.toInt();
  • 读取返回的头
//QList QNetworkReply::rawHeaderList () const //取到所有的头的键列表
QList list = reply->rawHeaderList();
//QByteArray QNetworkReply::rawHeader ( const QByteArray & headerName ) const //通过键名获取对应的值
for (int i = 0; i < list.size(); i++) 
{
		qDebug() << "header: " << list.at(i).data() << " " << reply->rawHeader(list.at(i));
}
  • 接收所有回复的数据
//QByteArray QIODevice::readAll ()
QByteArray  resp = reply->readAll();

3. 支持Https

支持HTTPS请求需要配置OpenSSL环境,Qt默认是不带SSl认证的,直接访问HTTPS会有错误信号。 环境配置:
需要对应的库文件 libeay32.dll和ssleay32.dll。需要下载libeay32.dll 和 ssleay32.dll两个库文件,将这两个库文件拷贝到程序生成目录下(即生成exe的同级目录)或者拷贝到QtNetwork模块的库文件目录中。可以在本地电脑搜索这两个库文件,直接拷贝就行。
QT实现一个Https客户端_第2张图片
并且在发送请求前设置一下:

	QSslConfiguration conf = request.sslConfiguration();
	conf.setPeerVerifyMode(QSslSocket::VerifyNone);
	conf.setProtocol(QSsl::AnyProtocol);
	request.setSslConfiguration(conf);

测试服务器:https://httpbin.org/

4. 请求认证

http请求的认证信息通过增加认证头来实现。用户名和密码常用的加密方式有basic和digest加密
Basic加密头格式:
Authorization: Basic base64(username:password)
Digest加密头格式:
Authorization: Digest MD5(username:realm:password)
这里设计了一个信号槽,如果访问需要认证,将自动调用需要校验的数据,用户名和密码;这里是在发送数据前,需要将认证信息传进去。

/*void QNetworkAccessManager::authenticationRequired ( QNetworkReply * reply, QAuthenticator * authenticator ) [signal]*/

	manager = new QNetworkAccessManager(this);
	connect(manager,SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)),this, SLOT(authRequiredReply(QNetworkReply*,QAuthenticator*)));
//实现的槽函数如下
void TestHttpClient::authRequiredReply(QNetworkReply *reply, QAuthenticator *auth)
{
	QString username = ui->username->text();
	QString password = ui->password->text();
	if (username.isEmpty() || password.isEmpty()) {
		return ;
	}
	auth->setUser(username);
	auth->setPassword(password);
}
	

你可能感兴趣的:(QT)