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

相关推荐
星海幻影2 分钟前
网络基础-超文本协议与内外网划分(超长版)
服务器·网络·安全
小白也有IT梦4 分钟前
域名绑定服务器小白教程
运维·nginx
有梦想的咕噜12 分钟前
Secure Shell(SSH) 是一种网络协议
运维·网络协议·ssh
dntktop23 分钟前
免费,WPS Office教育考试专用版
运维
苹果醋31 小时前
C语言 strlen 函数 - C语言零基础入门教程
java·运维·spring boot·mysql·nginx
loong_XL2 小时前
automa 浏览器自动化工具插件
运维·自动化
ForRunner1232 小时前
在 Node.js 中解决极验验证码:使用 Puppeteer 自动化
运维·node.js·自动化
IT19956 小时前
Linux笔记-对Linux环境变量的进一步认识(2024-08-09)
linux·运维·笔记·运维开发
Yanbin_Q7 小时前
Vagrant 没了 VirtualBox 的话可以配 Qemu
运维·ruby·vagrant
张铁铁是个小胖子9 小时前
jwt用户登录,网关给微服务传递用户信息,以及微服务间feign调用传递用户信息
java·服务器·微服务