将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 加密流量,从而提高安全性,防止中间人攻击。

相关推荐
woshilys22 分钟前
sql server 查询对象的修改时间
运维·数据库·sqlserver
疯狂飙车的蜗牛1 小时前
从零玩转CanMV-K230(4)-小核Linux驱动开发参考
linux·运维·驱动开发
恩爸编程2 小时前
探索 Nginx:Web 世界的幕后英雄
运维·nginx·nginx反向代理·nginx是什么·nginx静态资源服务器·nginx服务器·nginx解决哪些问题
Michaelwubo3 小时前
Docker dockerfile镜像编码 centos7
运维·docker·容器
远游客07133 小时前
centos stream 8下载安装遇到的坑
linux·服务器·centos
好像是个likun3 小时前
使用docker拉取镜像很慢或者总是超时的问题
运维·docker·容器
LIKEYYLL5 小时前
GNU Octave:特性、使用案例、工具箱、环境与界面
服务器·gnu
云云3216 小时前
搭建云手机平台的技术要求?
服务器·线性代数·安全·智能手机·矩阵
云云3216 小时前
云手机有哪些用途?云手机选择推荐
服务器·线性代数·安全·智能手机·矩阵
ZachOn1y6 小时前
计算机网络:应用层 —— 应用层概述
计算机网络·http·https·应用层·dns