将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

接下来,修改你的服务器代码以使用 QSslSocketQSslConfiguration 来支持 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"

关键修改点

  1. 使用 QSslSocket 代替 QTcpSocket

    • QSslSocketQTcpSocket 的扩展,支持加密通信。
    • incomingConnection 方法中,使用 QSslSocket 设置 Socket 描述符,并启动 SSL 加密。
  2. 加载证书和私钥

    • 在构造函数中加载证书 (cert.pem) 和私钥 (key.pem) 文件,并设置 SSL 配置。
    • sslConfig.setLocalCertificatesslConfig.setPrivateKey 用于设置证书和私钥。
  3. 修改监听端口

    • 将监听端口从 80 修改为 443,这是 HTTPS 的标准端口。
  4. 处理加密连接

    • incomingConnection 中,调用 socket->startServerEncryption() 启动加密。
    • 连接 QSslSocket::encrypted 信号到 handleConnection 槽,确保数据在加密状态下读取。

运行服务器

确保你的证书 (cert.pem) 和私钥文件 (key.pem) 在可执行文件的同一目录下,然后编译并运行服务器。服务器现在将监听 443 端口,并使用 SSL/TLS 加密流量,从而提高安全性,防止中间人攻击。

相关推荐
嚯——哈哈13 分钟前
AWS云服务器:开启高效计算的新纪元
服务器·云计算·aws
嚯——哈哈13 分钟前
从入门到精通:解析如何使用亚马逊云服务器(AWS EC2)
运维·服务器·aws
Elastic 中国社区官方博客1 小时前
Elasticsearch 中的热点以及如何使用 AutoOps 解决它们
大数据·运维·elasticsearch·搜索引擎·全文检索
DC_BLOG1 小时前
Linux-Nginx虚拟主机
linux·运维·nginx
坐公交也用券1 小时前
使用Python3实现Gitee码云自动化发布
运维·gitee·自动化
1900432 小时前
linux复习5:C prog
linux·运维·服务器
朝九晚五ฺ3 小时前
【Linux探索学习】第十五弹——环境变量:深入解析操作系统中的进程环境变量
linux·运维·学习
李迟3 小时前
某Linux发行版本无法使用nodejs程序重命名文件问题的研究
java·linux·服务器
施努卡机器视觉3 小时前
电解车间铜业机器人剥片技术是现代铜冶炼过程中自动化和智能化的重要体现
运维·机器人·自动化
徐浪老师3 小时前
深入实践 Shell 脚本编程:高效自动化操作指南
运维·chrome·自动化