Qt中使用HTTPS

一、HTTPS和HTTP区别

1. 从定义上看

HTTP: HyperText Transfer Protocol

HTTPS: HyperText Transfer Protocol over Secure Socket Layer

2. 从分层上看

HTTP: HTTP -> Socket API -> TCP/QUIC①

HTTPS: HTTP -> 安全层 -> Socket API -> TCP/QUIC

3. 安全层

显而易见,HTTPS比HTTP多了一个“安全层②”。

所谓“安全层”,无非是为了保证数据安全。其中涉及的技术,简单来说有三个:

  • 数据加密:防止数据被第三方窥探到。通过AES、DES、RSA等加解密算法实现
  • 数据完整性:防止数据被破坏。通过各种散列函数算法实现,如MD4/MD5,SHA-1/SHA-256等
  • 通信双方认证:防止冒充。通过证书技术实现

4. 安全层实现

安全层实现主流且常见的有OpenSSLMbed TLS,双方区别主要应用场景不同:

  • OpenSSL庞大,主要应用于PC、高端CPU上,如支持Linux的CPU
  • Mbed TLS更加轻量,可以在一些低端CPU,如Arm的Cortex-M系列上运行。在IoT领域,Mbed TLS大放异彩

二、Qt HTTPS环境配置

Qt的安全层使用的是OpenSSL,支持HTTPS请求需要配置OpenSSL环境。

不过,无需自己编译OpenSSL或者满世界找编译好的库。Qt的安装路径下已经有现成的dll库

以Mingw编译环境为例,这两个dll位于:C:\Qt\Qt5.9.1\Tools\mingw530_32\opt\bin。

把libeay32.dll 和 ssleay32.dll拷贝到程序生成目录下(即生成exe的同级目录)或者加入到系统环境变量里都可以

三、HTTPS代码示例

1. 准备工作

  • HTTPS服务器:https://httpbin.org
  • 调试工具:curl

2.示例功能

  • 向HTTPS服务器发送POST方法,获取Json格式数据,显示在一个QPlainText控件里
  • 向HTTPS服务器发送GET方法,获取一个PNG格式图片,显示在一个QLabel控件里

3.UI和数据分离

HttpClient负责HTTPS网络连接,数据获取;获取数据后发送Signal给HttpClientView,HttpClientView负责数据结果呈现。

4.示例代码

4.1 HttpClient

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

---HttpClient.h

#ifndef HTTPSCLIENT_H

#define HTTPSCLIENT_H

#include <QString>

#include <QByteArray>

#include <QNetworkAccessManager>

#include <QNetworkReply>

class HttpClient : public QObject

{

    Q_OBJECT

public:

    enum HttpMethod{

        POST = 0,

        GET, DELETE, PUT

    };

    Q_ENUM(HttpMethod)

    HttpClient();

    ~HttpClient();

    void doRequest(HttpClient::HttpMethod method, QString& url);

private slots:

    void postFinishSlot();

    void httpErrorSlot(QNetworkReply::NetworkError err);

signals:

    void postFinish(int statusCode, QByteArray& response);

    void httpError(QNetworkReply::NetworkError err);

private:

    QNetworkAccessManager *mAccessManager;

    QNetworkReply *mReply;

};

#endif // HTTPSCLIENT_H

---HttpClient.cpp

#include <QSsl>

#include <QUrl>

#include <QSslSocket>

#include <QSslConfiguration>

#include <QNetworkRequest>

#include <QNetworkReply>

#include <QVariant>

#define LOG_TAG "HttpClient"

#include "../log/log.h"

#include "HttpClient.h"

HttpClient::HttpClient() : mAccessManager(NULL)

{

    log_debug("NetworkAccessManager init...");

    mAccessManager = new QNetworkAccessManager(this);

    log_debug("NetworkAccessManager init done.");

}

HttpClient::~HttpClient()

{

    log_info("desc");

    if (mAccessManager) {

        delete mAccessManager;

        mAccessManager = NULL;

    }

}

void HttpClient::doRequest(HttpClient::HttpMethod method, QString &url)

{

    log_info("do request...");

    QNetworkRequest request;

    QSslConfiguration cfg = request.sslConfiguration();

    cfg.setPeerVerifyMode(QSslSocket::VerifyNone);

    cfg.setProtocol(QSsl::AnyProtocol);

    request.setSslConfiguration(cfg);

    request.setUrl(QUrl(url));

    if (method == POST) {

        request.setRawHeader("Content-Type: ""application/json;charset=utf-8");

        request.setRawHeader("Accept""application/json");

        QByteArray data;

        data.clear();

        mReply = mAccessManager->post(request, data);

    else if (method == GET) {

        request.setRawHeader("Content-Type: ""image/png");

        request.setRawHeader("Accept""image/png");

        mReply = mAccessManager->get(request);

    }

    connect(mReply, SIGNAL(finished()), this, SLOT(postFinishSlot()));

    connect(mReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(httpErrorSlot(QNetworkReply::NetworkError)));

}

void HttpClient::postFinishSlot()

{

    QVariant statusCode = mReply->attribute(QNetworkRequest::HttpStatusCodeAttribute);

    int code = statusCode.toInt();

    QByteArray resp = mReply->readAll();

    QList<QByteArray> hdrNames = mReply->rawHeaderList();

    log_info("response headers:");

    for (int i = 0; i < hdrNames.size(); i ++) {

        QByteArray hdrName = hdrNames.at(i);

        QByteArray hdrCtx = mReply->rawHeader(hdrName);

        log_debug("%s: %s", hdrName.constData(), hdrCtx.constData());

    }

    emit postFinish(code, resp);

}

void HttpClient::httpErrorSlot(QNetworkReply::NetworkError err)

{

    emit httpError(err);

}

  

4.2 HttpClientView

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

---HttpClientView.h

#ifndef HTTPCLIENTVIEW_H

#define HTTPCLIENTVIEW_H

#include <QWidget>

#include "HttpClient.h"

namespace Ui {

class HttpClientView;

}

class HttpClientView : public QWidget

{

    Q_OBJECT

public:

    explicit HttpClientView(QWidget *parent = 0);

    ~HttpClientView();

private:

    void init();

    void initUI();

    void initSlot();

private slots:

    void onBtnExecuteClicked();

    void postFinishSlot(int statusCode, QByteArray& response);

    void httpErrorSlot(QNetworkReply::NetworkError err);

private:

    Ui::HttpClientView *ui;

    HttpClient *mHttpClient;

};

#endif // HTTPCLIENTVIEW_H

---HttpClientView.cpp

#define LOG_TAG "HttpView"

#include "../log/log.h"

#include <QImage>

#include <QPixmap>

#include "HttpClientView.h"

#include "ui_httpclientview.h"

HttpClientView::HttpClientView(QWidget *parent) :

    QWidget(parent), mHttpClient(NULL),

    ui(new Ui::HttpClientView)

{

    ui->setupUi(this);

    init();

    initUI();

    initSlot();

}

HttpClientView::~HttpClientView()

{

    if (mHttpClient) {

        delete mHttpClient;

        mHttpClient = NULL;

    }

    delete ui;

}

void HttpClientView::init()

{

    mHttpClient = new HttpClient();

    connect(mHttpClient, SIGNAL(postFinish(int,QByteArray&)), this, SLOT(postFinishSlot(int,QByteArray&)));

    connect(mHttpClient, SIGNAL(httpError(QNetworkReply::NetworkError)), this, SLOT(httpErrorSlot(QNetworkReply::NetworkError)));

}

void HttpClientView::initUI()

{

    ui->labelImage->setStyleSheet("{border:2px dotted #242424;}");

}

void HttpClientView::initSlot()

{

    connect(ui->btnExecute, SIGNAL(clicked()), this, SLOT(onBtnExecuteClicked()));

}

void HttpClientView::onBtnExecuteClicked()

{

    int scheme = ui->cBoxScheme->currentIndex();

    int method = ui->cBoxMethod->currentIndex();

    ui->plainTextEdit->appendPlainText("request...");

    log_info("http scheme %d, method %d", scheme, method);

    if (0 == method) {

        QString url("https://httpbin.org/post");

        mHttpClient->doRequest(HttpClient::POST, url);

    else if (1 == method) {

        QString url("https://httpbin.org/image/png");

        mHttpClient->doRequest(HttpClient::GET, url);

    }

}

void HttpClientView::postFinishSlot(int statusCode, QByteArray& response)

{

    int size = response.size();

    ui->plainTextEdit->appendPlainText("request finish.");

    log_info("response code: %d, data size: %d", statusCode, size);

    if (size > 0) {

        if (0 == ui->cBoxMethod->currentIndex()) {

            ui->plainTextEdit->appendPlainText(QString(response));

        else if (1 == ui->cBoxMethod->currentIndex()) {

            QImage img;

            bool res = img.loadFromData(response);

            if (res) {

                ui->labelImage->setAlignment(Qt::AlignCenter);

                ui->labelImage->setPixmap(QPixmap::fromImage(img));

            else {

                log_error("error convert image from http response data!");

            }

        }

    }

}

void HttpClientView::httpErrorSlot(QNetworkReply::NetworkError err)

{

    log_error("http error: %d\r\n", err);

}

  

4.3 UI

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

<?xml version="1.0" encoding="UTF-8"?>

<ui version="4.0">

 <class>HttpClientView</class>

 <widget class="QWidget" name="HttpClientView">

  <property name="geometry">

   <rect>

    <x>0</x>

    <y>0</y>

    <width>634</width>

    <height>490</height>

   </rect>

  </property>

  <property name="font">

   <font>

    <pointsize>11</pointsize>

    <weight>75</weight>

    <bold>true</bold>

   </font>

  </property>

  <property name="windowTitle">

   <string>HttpClientView</string>

  </property>

  <layout class="QGridLayout" name="gridLayout">

   <item row="0" column="0" rowspan="4">

    <widget class="QPlainTextEdit" name="plainTextEdit">

     <property name="minimumSize">

      <size>

       <width>370</width>

       <height>0</height>

      </size>

     </property>

     <property name="font">

      <font>

       <pointsize>11</pointsize>

       <weight>50</weight>

       <bold>false</bold>

      </font>

     </property>

    </widget>

   </item>

   <item row="0" column="1" colspan="4">

    <widget class="QLabel" name="labelImage">

     <property name="enabled">

      <bool>true</bool>

     </property>

     <property name="minimumSize">

      <size>

       <width>240</width>

       <height>240</height>

      </size>

     </property>

     <property name="maximumSize">

      <size>

       <width>16777215</width>

       <height>16777215</height>

      </size>

     </property>

     <property name="font">

      <font>

       <weight>50</weight>

       <bold>false</bold>

      </font>

     </property>

     <property name="styleSheet">

      <string notr="true">border:2px dotted #242424;</string>

     </property>

     <property name="text">

      <string/>

     </property>

    </widget>

   </item>

   <item row="1" column="1">

    <spacer name="verticalSpacer_2">

     <property name="orientation">

      <enum>Qt::Vertical</enum>

     </property>

     <property name="sizeHint" stdset="0">

      <size>

       <width>20</width>

       <height>144</height>

      </size>

     </property>

    </spacer>

   </item>

   <item row="1" column="3">

    <spacer name="verticalSpacer">

     <property name="orientation">

      <enum>Qt::Vertical</enum>

     </property>

     <property name="sizeHint" stdset="0">

      <size>

       <width>20</width>

       <height>144</height>

      </size>

     </property>

    </spacer>

   </item>

   <item row="2" column="1">

    <layout class="QVBoxLayout" name="verticalLayout">

     <item>

      <widget class="QLabel" name="labelScheme">

       <property name="enabled">

        <bool>true</bool>

       </property>

       <property name="text">

        <string>Schemes</string>

       </property>

      </widget>

     </item>

     <item>

      <widget class="QComboBox" name="cBoxScheme">

       <property name="font">

        <font>

         <weight>50</weight>

         <bold>false</bold>

        </font>

       </property>

       <item>

        <property name="text">

         <string>HTTPS</string>

        </property>

       </item>

       <item>

        <property name="text">

         <string>HTTP</string>

        </property>

       </item>

      </widget>

     </item>

    </layout>

   </item>

   <item row="2" column="2">

    <spacer name="horizontalSpacer">

     <property name="orientation">

      <enum>Qt::Horizontal</enum>

     </property>

     <property name="sizeHint" stdset="0">

      <size>

       <width>8</width>

       <height>20</height>

      </size>

     </property>

    </spacer>

   </item>

   <item row="2" column="3">

    <layout class="QVBoxLayout" name="verticalLayout_2">

     <item>

      <widget class="QLabel" name="labelHttp">

       <property name="enabled">

        <bool>true</bool>

       </property>

       <property name="text">

        <string>Methods</string>

       </property>

      </widget>

     </item>

     <item>

      <widget class="QComboBox" name="cBoxMethod">

       <property name="font">

        <font>

         <weight>50</weight>

         <bold>false</bold>

        </font>

       </property>

       <item>

        <property name="text">

         <string>POST</string>

        </property>

       </item>

       <item>

        <property name="text">

         <string>GET</string>

        </property>

       </item>

       <item>

        <property name="text">

         <string>DELETE</string>

        </property>

       </item>

       <item>

        <property name="text">

         <string>PUT</string>

        </property>

       </item>

      </widget>

     </item>

    </layout>

   </item>

   <item row="2" column="4">

    <spacer name="horizontalSpacer_2">

     <property name="orientation">

      <enum>Qt::Horizontal</enum>

     </property>

     <property name="sizeHint" stdset="0">

      <size>

       <width>64</width>

       <height>20</height>

      </size>

     </property>

    </spacer>

   </item>

   <item row="3" column="1" colspan="4">

    <widget class="QPushButton" name="btnExecute">

     <property name="minimumSize">

      <size>

       <width>240</width>

       <height>0</height>

      </size>

     </property>

     <property name="font">

      <font>

       <pointsize>11</pointsize>

      </font>

     </property>

     <property name="styleSheet">

      <string notr="true">background-color: rgb(73, 144, 226);

color: rgb(255, 255, 255);</string>

     </property>

     <property name="text">

      <string>执行</string>

     </property>

    </widget>

   </item>

  </layout>

  <zorder>layoutWidget</zorder>

  <zorder>layoutWidget</zorder>

  <zorder>plainTextEdit</zorder>

  <zorder>labelImage</zorder>

  <zorder>btnExecute</zorder>

  <zorder>horizontalSpacer</zorder>

  <zorder>verticalSpacer</zorder>

  <zorder>horizontalSpacer_2</zorder>

  <zorder>verticalSpacer_2</zorder>

 </widget>

 <resources/>

 <connections/>

</ui>

  

4.4 关键代码

四、报错、原因分析及解决

1. qt.network.ssl: QSslSocket: cannot call unresolved function

原因:未找到libeay32.dll 和 ssleay32.dll,检查环境设置。

2.QNetworkReply::UnknownNetworkError

原因:由问题1引起,解决方式同上。 

转载于:https://www.cnblogs.com/rockyching2009/p/15474343.html

Qt是一个跨平台的软件开发框架,主要用于创建桌面应用程序、移动应用和嵌入式系统。其Qt对于HTTPS的支持使得开发者能够构建安全的网络通信功能,特别是在处理敏感数据(如用户登录信息)传输时。 在QtHTTPS(HTTP Secure)通常通过QNetworkAccessManager类来实现,这是Qt提供的一种网络访问管理器,用于发起HTTP/HTTPS请求。为了使用HTTPS,你需要: 1. **添加SSL/TLS支持**:确保你的Qt安装包含了SSL库,例如OpenSSL或NSS,因为这些库提供了加密通信的基础。 2. **初始化QSslSocket**:在QNetworkRequest指定"https"作为URL协议,然后使用QSslSocket连接到服务器。QSslSocket是Qt提供的SSL/TLS安全套接字,用于加密网络连接。 ```cpp QSslConfiguration sslConfig; sslConfig.setProtocol(QSsl::TlsV1_2); // 设置使用的TLS版本 QSslSocket socket(&sslConfig); socket.connectToHost(host, port); ``` 3. **设置证书验证**:根据应用场景,可能需要验证服务器的证书。你可以设置QSslSocket的验证模式,比如QSslSocket::VerifyPeerCertificate用来检查证书的有效性。 4. **发送HTTPS请求**:使用QNetworkAccessManager发起HTTPS GET或POST等操作,传递QSslSocket实例给manager。 ```cpp QNetworkRequest request(url); request.setRawHeader("Content-Type", "application/json"); QNetworkReply* reply = manager.get(request, socket); reply->finished.connect([](QNetworkReply *reply) { // 处理响应数据 }); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值