将C++搭建的简单HTTP服务器升级为 HTTPS 服务器
HTTP 协议是不加密的,容易遭受中间人攻击(MITM)。为了提高安全性,你可以将服务器升级为 HTTPS 服务器,使用 SSL/TLS 加密流量。下面是如何将以下链接文章中的 HTTP 服务器修改为 HTTPS 服务器的步骤:
ps:使用C++构建一个简单的HTTP服务器,处理请求和响应_html请求 c++服务端-CSDN博客
使用 OpenSSL 生成自签名证书
首先,你需要生成自签名证书。以下是一个简单的命令:
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
这个命令会生成一个有效期为 365 天的自签名证书 (cert.pem
) 和私钥文件 (key.pem
)。
修改服务器代码以支持 HTTPS
接下来,修改你的服务器代码以使用 QSslSocket
和 QSslConfiguration
来支持 HTTPS。
#include <QCoreApplication>
#include <QTcpServer>
#include <QSslSocket>
#include <QDebug>
#include <QTextStream>
#include <QSslConfiguration>
#include <QSslKey>
#include <QSslCertificate>
class HttpsServer : public QTcpServer {
Q_OBJECT
public:
HttpsServer(QObject *parent = nullptr) : QTcpServer(parent) {
// 加载证书和私钥
QFile certFile("cert.pem");
QFile keyFile("key.pem");
if (!certFile.open(QIODevice::ReadOnly) || !keyFile.open(QIODevice::ReadOnly)) {
qCritical() << "Failed to open certificate or key file.";
return;
}
QSslCertificate certificate(&certFile, QSsl::Pem);
QSslKey privateKey(&keyFile, QSsl::Rsa, QSsl::Pem);
certFile.close();
keyFile.close();
sslConfig.setLocalCertificate(certificate);
sslConfig.setPrivateKey(privateKey);
sslConfig.setPeerVerifyMode(QSslSocket::VerifyNone); // 这里设置为 VerifyNone 仅用于测试
}
protected:
void incomingConnection(qintptr socketDescriptor) override {
QSslSocket *socket = new QSslSocket(this);
if (socket->setSocketDescriptor(socketDescriptor)) {
socket->setSslConfiguration(sslConfig);
socket->startServerEncryption();
connect(socket, &QSslSocket::encrypted, this, &HttpsServer::handleConnection);
connect(socket, &QSslSocket::disconnected, socket, &QSslSocket::deleteLater);
} else {
qWarning() << "Failed to set socket descriptor.";
delete socket;
}
}
private slots:
void handleConnection() {
QSslSocket *socket = qobject_cast<QSslSocket *>(sender());
if (!socket) return;
connect(socket, &QSslSocket::readyRead, this, &HttpsServer::handleRequest);
}
void handleRequest() {
QSslSocket *socket = qobject_cast<QSslSocket *>(sender());
if (!socket) return;
QTextStream in(socket);
QString request = in.readAll();
qDebug() << "Received encrypted request:\n" << request;
// 构建 HTTP 响应
QString response = "HTTP/1.1 200 OK\r\n";
response += "Content-Type: text/html; charset=UTF-8\r\n";
response += "\r\n";
response += "<html><body><h1>Hello, World!</h1></body></html>";
// 发送响应
QTextStream out(socket);
out << response;
socket->flush();
socket->close();
}
private:
QSslConfiguration sslConfig;
};
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
HttpsServer server;
if (!server.listen(QHostAddress::Any, 443)) { // 使用 443 端口
qCritical() << "Unable to start the server:" << server.errorString();
return 1;
}
qDebug() << "Listening on port 443...";
return a.exec();
}
#include "main.moc"
关键修改点
-
使用
QSslSocket
代替QTcpSocket
:QSslSocket
是QTcpSocket
的扩展,支持加密通信。- 在
incomingConnection
方法中,使用QSslSocket
设置 Socket 描述符,并启动 SSL 加密。
-
加载证书和私钥:
- 在构造函数中加载证书 (
cert.pem
) 和私钥 (key.pem
) 文件,并设置 SSL 配置。 sslConfig.setLocalCertificate
和sslConfig.setPrivateKey
用于设置证书和私钥。
- 在构造函数中加载证书 (
-
修改监听端口:
- 将监听端口从 80 修改为 443,这是 HTTPS 的标准端口。
-
处理加密连接:
- 在
incomingConnection
中,调用socket->startServerEncryption()
启动加密。 - 连接
QSslSocket::encrypted
信号到handleConnection
槽,确保数据在加密状态下读取。
- 在
运行服务器
确保你的证书 (cert.pem
) 和私钥文件 (key.pem
) 在可执行文件的同一目录下,然后编译并运行服务器。服务器现在将监听 443 端口,并使用 SSL/TLS 加密流量,从而提高安全性,防止中间人攻击。