Все привет! Если кто знает, подскажите пожалуйста, как работать с certificates? Вот например. Я сделал запрос через QNetworkAccessManager. Соединил сигнал sslErrors со своим слотом. Захожу на какой-то сайт через https. А дальше как? Если у этого домена есть сертификат, я должен вывалиться в слот, соединенный с сигналом sslErrors, у QNetworkReply взять сертификат и проверить его? А как проверять... и главное с чем сравнивать? В программе должна быть база данных сертификатов? Просто дали задание, а как тут быть неясно....
Огромное спасибо за любую информацию!
Самая распространенная ошибка при работе с сертификатом - когда сертификат подписан локально (т.е. НЕ через службу подписи
В этом случае браузеры выдают предупреждение мол так и так - сертификат неизвестно откуда и неизвестно кем подписан.
В Qt - выполнение попадет в слот, с ошибкой QSslError::HostNameMismatch
Как поступить - решать Вам, если вызовете слот ignoreSslError() тогда соединение продолжится.
Получить сертификат можно с помощью метода QSslCertificate QSslError::certificate () const
Его безусловно можно сравнить с любым другим ( bool QSslCertificate::operator== ( const QSslCertificate & other ) const ).
Вот)
З.Ы. повторю - это лишь одна из множества ошибок)
Круто, большое спасибо за ответ!!!
А как Большие Браузеры поступают?) Вот попался непонятный сертификат с какого-то сайта (просроченный, реально выданный другому хосту, untrusted и пр.). Они (Большие Браузеры) предупреждают об этом этом понятно. Если пользователь не хочет продолжать - то просто ничего не делаем... Если хочет, то я должен занести этот сертификат в локальную базу и потом когда снова вхожу на этот сайт - ищу в этой локальной базе его сертификат, и если нахожу, то вызываю ignoreSslErrors и радуюсь жизни? При этом как я понимаю, работать нужно примерно так (псевдокод):
slotSslErrors(QList<QSslError>& err....)
{
QList<QsslCertificate> certificates = err.certificates();//в цикле все сертификаты берем...
defConf = QSslConfiguration::defaultConfiguration();
defConf->setCaCertificates(certificates);
QSslConfiguration::setDefaultConfiguration(defConf);
}
slotSslErrors(QList<QSslError>& err....)
{
QList<QsslCertificate> certificates = err.certificates();//в цикле все сертификаты берем...
defConf = QSslConfiguration::defaultConfiguration();
defConf->setCaCertificates(certificates);
QSslConfiguration::setDefaultConfiguration(defConf);
}
нет, надо примерно так:
slotSslErrors(QList<QSslError>& err)
{
foreach( const QSslError &e, err )
{
}
}
Ну да, я коммент насчет цикла написал... ) Сам foreach опустил чтоб не загромождать... Я имею ввиду идею правильно понимаю? Просто я так делал, а при заходе на этот же сайт еще раз (не выходя из программы), снова вываливался в слот sslErrors с теми же ошибками касаемо сертификатов, что и в первый раз.... Или стоп... так и должно быть? При reload-e какбы новый handshake у сокетов происходит? А можно как-то сделать чтобы вот принял я этот (пускай невалидный) сертификат, и больше для этого сайта в слот sslErrors не попадаю... Или так никак не сделать?)
я бы сделал как-то так... )
slotSslErrors(QList<QSslError>& err)
{
foreach( const QSslError &e, err )
{
switch( e.error() )
{
case QSslError::HostNameMismatch:
{
if( localDatabase.contains( e.certificate() )
{
// Игнорируем ошибку, т.к. сертификат есть у нас в БД
((QNetworkReply*)sender())->ignoreSslErrors( QList<QSslError>() << e ))
return;
}
else if( askUser( e.certificate() )
{
// Спрашиваем юзера, хочет ли он добавить сертификат в локальную БД, если да
localDatabase << e.certificate();
// Игнорируем ошибку
((QNetworkReply*)sender())->ignoreSslErrors( QList<QSslError>() << e ))
return;
}
return; // соединение будет закрыто, т.к. сертификат не в бд и т.к. пользователь не захотел добавить его в бд
}
// Обработка других ошибок
}
}
}
А в случае, если у хоста все нормально (например, https://google.com) с сертификатами (т.е. я не попадаю в слот ошибок ssl), как эти сертификаты тогда можно достать? Ведь если я правильно понимаю, тогда в БД должны быть все сертификаты, с которыми работает браузер... И нормальные, и те, с которыми что-то не так....
И такой вопрос.... Qt (через механизмы openSSL) сам (на "низком" - не пользовательском уровне) при https-запросе отправляет информацию о сертификате хоста в центры CA? Т.е. вот этот механизм меня, как конечного пользователя Qt, не должен интересовать вообще, так?
И, наверное, последний вопрос... Почему именно QSslError::HostNameMismatch? Почему не CertificateExpired или не CertificateUntrusted? Можно где-то подробнее об этих ошибках почитать? А то в Qt Assistant только идентификаторы указаны этих ошибок и больше ничего на найти.... и не нагуглить(
Ок, узнаю что-то новое, напишу тут) Еще раз спасибо!
Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)