Написание безопасных серверных приложений с Qt

0

Я последовал за учебником "Написание безопасных серверных приложений с Qt" (https://blog.quickmediasolutions.com/2012/09/18/writing-secure-server-applications-with-qt.html), но у меня есть ошибка:

Изображение 174551

CSampleServer.h

#ifndef CSAMPLESERVER_H
#define CSAMPLESERVER_H

#include <QTcpServer>

class CSampleServer : public QTcpServer
{
public:
    CSampleServer();

private:
    void incomingConnection(int);

signals:
    void StatusMessage(QString);
};

#endif // CSAMPLESERVER_H

CSampleServer.cpp

#include "CSampleServer.h"
#include "CSecureSocket.h"

CSampleServer::CSampleServer()
{
}

void CSampleServer::incomingConnection(int handle)
{
    CSecureSocket * socket = new CSecureSocket(this);
    connect(socket, SIGNAL(StatusMessage(QString)), SIGNAL(StatusMessage(QString)));
    socket->Process(handle);
}

CSecureSocket.h

#ifndef CSECURESOCKET_H
#define CSECURESOCKET_H

#include <QSslSocket>

class CSecureSocket : public QSslSocket
{
public:
    CSecureSocket();
    void Process(int);


signals:
    void StatusMessage(QString);
};

#endif // CSECURESOCKET_H

CSecureSocket.cpp

#include "CSecureSocket.h"
#include <QHostAddress>

CSecureSocket::CSecureSocket()
{
}

void CSecureSocket::Process(int handle)
{
    /* Emit a message indicating the address of the client. */
    setSocketDescriptor(handle);
    emit StatusMessage(tr("Incoming connection from %1.").arg(peerAddress().toString()));

    /* Set the certificate and private key. */
    setLocalCertificate("server.crt");
    setPrivateKey("server.key.insecure");

    /* Start the server encryption process and wait for it to complete. */
    startServerEncryption();
    if(waitForEncrypted())
    {
        emit StatusMessage("Session with client is now encrypted.");

        /* Respond with a basic HTTP message. */
        write("HTTP/1.1 200 OK\r\n"
              "Content-type: text/plain\r\n"
              "Content-length: 12\r\n"
              "\r\n"
              "Hello World!");

        emit StatusMessage("Message sent to client. Closing connection.");
    }
    else
        emit StatusMessage(tr("An error occurred: %1.").arg(errorString()));

    /* Close the connection once the data is written. */
    disconnectFromHost();
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "CSampleServer.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void OnStart();
    void OnStatusMessage(QString);

private:
    Ui::MainWindow *ui;
    CSampleServer m_server;
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    connect(&m_server, SIGNAL(StatusMessage(QString)), SLOT(OnStatusMessage(QString)));
    connect(ui->pushButton, SIGNAL(clicked()), SLOT(OnStart()));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::OnStart()
{
    quint16 port = ui->spinBox->value();
    if(m_server.listen(QHostAddress::Any, port))
        OnStatusMessage(tr("Listening on port %1...").arg(port));
    else
        OnStatusMessage(tr("Unable to listen on port %1.").arg(port));
}

void MainWindow::OnStatusMessage(QString message)
{
    ui->plainTextEdit->appendPlainText(message);
}

не могли бы вы мне помочь, пожалуйста. Заранее спасибо!

  • 0
    Как насчет показа вашего соответствующего кода неявным?
  • 0
    я обновил пост своим кодом
Показать ещё 2 комментария
Теги:
ssl
qt
sockets

3 ответа

3

Вы можете использовать SSL для создания защищенного сервера. Вот пример сервера с использованием QSsLSocket:

#include <QtNetwork>
#include <QMessageBox>

class server : public QTcpServer
{
    Q_OBJECT
public:
    explicit server(QObject *parent = 0);
    ~server();

    QSslSocket server_socket;

public slots:


      void tcpReady();

      void encrypted();

      void sslError( QList<QSslError> errors );

      bool start_listen(int port_no);

protected:
    void incomingConnection( int descriptor );

};

server::server(QObject *parent) :
    QTcpServer(parent)
{

    server_socket.setProtocol(QSsl::SslV3);

    QByteArray key;
    QByteArray cert;

    QFile file_key("server.key");
    if(file_key.open(QIODevice::ReadOnly))
    {
        key = file_key.readAll();
        file_key.close();
    }
    else
    {
        qDebug() << file_key.errorString();
    }

    QFile file_cert("server.crt");
    if(file_cert.open(QIODevice::ReadOnly))
    {
        cert = file_cert.readAll();
        file_cert.close();
    }
    else
    {
        qDebug() << file_cert.errorString();
    }


    QSslKey ssl_key(key, QSsl::Rsa,QSsl::Pem,QSsl::PrivateKey,"server");

    QSslCertificate ssl_cert(cert);

    server_socket.addCaCertificate(ssl_cert);
    server_socket.setLocalCertificate(ssl_cert);
    server_socket.setPrivateKey(ssl_key);


    connect( &server_socket, SIGNAL(sslErrors(QList<QSslError>)),
            this, SLOT(sslError(QList<QSslError>)) );

    connect(&server_socket,SIGNAL(encrypted()),this,SLOT(encrypted()));

    server_socket.setSocketOption(QAbstractSocket::KeepAliveOption, true );
}

server::~server()
{
    server_socket.disconnectFromHost();
    server_socket.waitForDisconnected();
}

void server::tcpReady()
{
    QByteArray array = server_socket.read( server_socket.bytesAvailable() );
    //...
}

void server::encrypted()
{
    connect( &server_socket, SIGNAL(readyRead()),
             this, SLOT(tcpReady()) );
    emit connection_established();
}

void server::sslError(QList<QSslError> errors)
{
    QString erroStr="";
    foreach (const QSslError &e, errors)
        erroStr.append(e.errorString()).append("\n");

    QMessageBox::warning( (QWidget *)this->parent(), tr("Error"),erroStr );

    server_socket.ignoreSslErrors();
}


bool server::start_listen(int port_no)
{
    if( !this->listen( QHostAddress::Any, port_no ) )
    {
        QMessageBox::warning( (QWidget *)this->parent(), tr("Error!"), tr("Cannot listen to port %1").arg(port_no) );

    }
    else
        return true;
}

void server::incomingConnection(int descriptor)
{
    if(server_socket.state()!=QAbstractSocket::UnconnectedState)
        return;
    if( !server_socket.setSocketDescriptor( descriptor ) )
    {
        QMessageBox::warning( (QWidget *)this->parent(), tr("Error!"), tr("Socket error!") );
        return;
    }
    else
    {
        server_socket.startServerEncryption();
    }
}

Вы должны создать файл server.key и server.crt для вашего приложения.

  • 0
    хорошее решение @Nejat! сейчас попробую в надежде что все будет хорошо: D
  • 0
    хорошо для сервера https?
Показать ещё 2 комментария
1

Это использование:

CSecureSocket * socket = new CSecureSocket(this);

несовместимо с этой декларацией/определением:

CSecureSocket();

Пытаться:

CSecureSocket* socket = new CSecureSocket();

...

  • 0
    я уже внес это изменение ... текущая ошибка сейчас: D: \ Users \ x \ Documents \ QT Projects \ SSLSocket \ CSecureSocket.cpp: 12: ошибка: неопределенная ссылка на `CSecureSocket :: StatusMessage (QString) '
  • 0
    Разве у вашего connect () нет другого параметра объекта? Мне кажется, что вы подключаете сигнал CSecureSocket::StatusMessage(QString) к себе. Попробуйте connect(socket, SIGNAL(StatusMessage(QString)), this, SIGNAL(StatusMessage(QString))) или что-то в этом роде ...
Показать ещё 1 комментарий
0

Проблема в том, что файлы moc_ * не были созданы для классов CSampleServer и CSecureSocket.

Для этого примера вам необходимо:

  1. добавьте макрос Q_OBJECT в определения классов CSampleServer.h и CSecureSocket.h
  2. очистить проект
  3. запустите qmake и убедитесь, что файлы moc_ * есть.
  4. снова создайте проект, в этот момент проблема строительства должна исчезнуть.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню