I have a program built with Qt creator. I need to send an https post to Google's C2DM servers.
When I try using QSslSocket, it says that my SSL is not working.
The Qt documentation states that it doesn't ship with SSL support for legal reasons, and QSslSocket is just a wrapper and that I need to install OpenSSL myself. I've tried copying the DLLs but it still doesn't work. Can someone walk me through the steps of installing OpenSSL and getting it to work with Qt Creator?
Why not use QNetworkAccessManager? I use something like this to post JSON to a web service:
void HttpPoster::post(){
if(!manager)
manager = new QNetworkAccessManager(this);
QSslConfiguration config = QSslConfiguration::defaultConfiguration();
config.setPeerVerifyMode(QSslSocket::VerifyNone);
//config.setProtocol(QSsl::TlsV1);
QNetworkRequest request ;
request.setUrl(QUrl("https://somehost.somedomain"));
request.setRawHeader("User-Agent", "MyApp");
request.setRawHeader("Content-type", "text/json");
request.setSslConfiguration(config);
if(!reply){
reply = manager->post(request,m_Data);
}
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),this,SLOT(handleErrors(QNetworkReply::NetworkError)));
connect(reply,SIGNAL(sslErrors(QList<QSslError>)),this,SLOT(handleSSLErrors(QList<QSslError>)));
connect(reply,SIGNAL(finished()),this,SLOT(replyFinished()));
}
There's some methods omitted (handle errors, handle replies, handle ssl errors, etc). You can find much better examples in the docs.
Related
I get a strange issue with my Qt-based software. The software uses QNetworkAccessManager to get and post information to a webserver using SSL encryption and the user have the option to use a proxy if needed. We do still have some limited information sent without SSL (to an http address, no added "s"), we use our own encryption for that part. Just haven't updated that part yet and that's not causing any issues right now (which actually is partially why this issue is strange).
You see, when I try to Post data using both a proxy and SSL I get error 103: "the remote host name was not found (invalid hostname)", but posting the data SSL and no proxy works fine, as does posting the data with proxy and no SSL. The exact same data can however be sent with both proxy and SSL using Postman, so there doesn't seem to be any issue with the data. Get works to get all data regardless of SSL and proxy.
Have anyone else had a similar issue or have an idea of what might be the cause? If so, have you found any solutions or workarounds?
Here's the proxy setup for the Get part:
nam = new QNetworkAccessManager(this);
connect(nam,SIGNAL(finished(QNetworkReply*)),this,SLOT(namFinished(QNetworkReply*)));
if(portalCommSettingsVO.isUseProxy()){
QNetworkProxy proxy(QNetworkProxy::HttpCachingProxy, portalCommSettingsVO.getProxyUrl(), static_cast<quint16>(portalCommSettingsVO.getProxyPort()));
if(!portalCommSettingsVO.getProxyUser().operator ==("")){
proxy.setUser(portalCommSettingsVO.getProxyUser());
proxy.setPassword(portalCommSettingsVO.getProxyPassword());
}
nam->setProxy(proxy);
}else{
nam->setProxy(QNetworkProxy::NoProxy);
}
And here's where I connect and Get the data:
QString routingUrlString = Utils::getUrlRoutingServer();
routingUrlString.append(QString::number(Id));
QUrl routingUrl(routingUrlString);
QNetworkRequest routingRequest;
routingRequest.setSslConfiguration(QSslConfiguration::defaultConfiguration());
routingRequest.setUrl(routingUrl);
reply = nam->get(routingRequest);
connect(reply,SIGNAL(error(QNetworkReply::NetworkError)),this,SLOT(downloadError(QNetworkReply::NetworkError)));
connect(reply, SIGNAL(sslErrors(const QList<QSslError>)), this,SLOT(downloadSSLError(const QList<QSslError>)));
connect(reply,SIGNAL(finished()),this,SLOT(routingDownloadFinished()));
Compared to the proxy setup for the Post part:
nam = new QNetworkAccessManager(this);
connect(nam,SIGNAL(finished(QNetworkReply*)),this,SLOT(namFinished(QNetworkReply*)));
if(portalCommSettingsVO.isUseProxy()){
QNetworkProxy proxy(QNetworkProxy::HttpCachingProxy, portalCommSettingsVO.getProxyUrl(), static_cast<quint16>(portalCommSettingsVO.getProxyPort()));
if(!portalCommSettingsVO.getProxyUser().operator ==("")){
proxy.setUser(portalCommSettingsVO.getProxyUser());
proxy.setPassword(portalCommSettingsVO.getProxyPassword());
}
nam->setProxy(proxy);
}else{
nam->setProxy(QNetworkProxy::NoProxy);
}
And where I connect and try to post the data:
QUrl url(currentObject.getUploadUrl());
QUrlQuery query;
query.addQueryItem("mode", "save");
url.setQuery(query.query());
QNetworkRequest request;
request.setSslConfiguration(QSslConfiguration::defaultConfiguration());
request.setUrl(QUrl(url));
request.setHeader(QNetworkRequest::ContentTypeHeader, QString("application/x-www-form-urlencoded"));
reply = nam->post(request,arr);
connect(reply,SIGNAL(error(QNetworkReply::NetworkError)),this,SLOT(uploadError(QNetworkReply::NetworkError)));
connect(reply, SIGNAL(sslErrors(const QList<QSslError>)), this,SLOT(uploadSSLError(const QList<QSslError>)));
connect(reply,SIGNAL(finished()),this,SLOT(uploadFinished()));
Pretty similar right? I can't understand why the Post wont work!
PS. the "arr"-variable is an array of data in base64. The same data could be sent through Postman without difficulty so I doubt that's where the issue is.
I want to enter in the program, ip, username and password of a virtual server(vps), and the program checks that the username and password are correct or not.
I used the following code
void MainWindow::test()
{
QLoggingCategory::setFilterRules("qt.network.ssl.warning=false");
QNetworkAccessManager* manager = new QNetworkAccessManager(this);
QUrl url;
url.setHost("xx.xxx.xx.xx");
url.setPort(3389);
url.setUserName("administrator");
url.setPassword("xxxx");
manager->get(QNetworkRequest(url));
connect(manager,&QNetworkAccessManager::finished, this, &MainWindow::connFinished);
}
output:
QNetworkReply::NetworkError(ProtocolUnknownError)
please guide me
If you only want to know, if the host is online:
I would suggest you use connectToHost from QAbstractSocket Class. The RDP-Protocol is based on TCP/UDP according to Wikipedia and listens on 3389 (what you said in the comments.).
If the connection on TCP 3389 is successful, the host is online.
If you want to verify if the host is online and the authentication works you have to implement your own RDP-library such as FreeRDP, because Qt does not provide any core modules for RDP.
My application consists from two apps. And one of them may ask another to perform some commands through a REST call (call an URL on localhost). For this purposes we use QNetworkAccessManager (for put, get and post request).
Now there is a problem - device may go offline sometimes and when he does it - for some reason we can't use rest calls through access manager. It seems that it happen when network configuration that it uses is destroyed (like disabling Wifi adapter etc). When this configuration is restored (enabled Wifi), access manager starts work again.
Another detail - when we start app while we are offline - it works regardless of online state. It may be related to this.
This reproduces on both Win and Mac.
So the question is how can i reliably use QNetworkAccessManager for this purposes irregardless of devices online state? We use this manager only for localhost REST calls. What default network configuration or behavior should i set?
Example of usage below:
mNetManager = new QNetworkAccessManager(this);
QNetworkRequest request;
request.setRawHeader("User-Agent", "AppName/1.0");
request.setUrl(QUrl(url));
*reply = mNetManager->get(request);
Edit: online state is not required, since i need this access manager only for accessing local URLs on browser
It appears you can force network accessibility to get local content:
mNetManager = new QNetworkAccessManager(this);
QNetworkRequest request;
request.setRawHeader("User-Agent", "AppName/1.0");
request.setUrl(QUrl(url));
mNetManager->setNetworkAccessible(QNetworkAccessManager::Accessible); // <--
auto reply = mNetManager->get(request);
The QNetworkAccessManager have stuff for network availability. Why not using it?
QNetworkAccessManager * mNetManager = new QNetworkAccessManager(this);
connect(mNetManager, &QNetworkAccessManager::networkAccessibleChanged,
this, &YourClass::slotExecutedWhenNetworkAccessibilityChanges);
NetworkAccessibility netAcc = mNetManager->networkAccessible();
switch (netAcc) {
case QNetworkAccessManager::Accessible:
// You are online.
break;
case QNetworkAccessManager::NotAccessible:
// You are offline.
break;
case QNetworkAccessManager::UnknownAccessibility:
default:
// You know nothing, Jon Snow.
break;
}
I use Qt5's QWebView to load a https website, which need client certificate. I have installed client certificate and used chrome and ie browser to test ok. But it didn't work in the QWebView.
QNetworkRequest request;
request.setUrl(QUrl("https://mysite.com/default2.aspx"));
QSslConfiguration conf = request.sslConfiguration();
//get the client certificate
QByteArray certData = getCertInWindowsMyStore();
QSslCertificate sslCert(certData, QSsl::Der);
conf.setLocalCertificate(sslCert);
request.setSslConfiguration(conf);
ui->webView->load(request);
I print the certicate's subjectinfo which is correct.
I seach some infomation from google. Someone says I have to set the private key, someone didn't set and it also works fine. How it works? And I think that I used chrome browser to visit that website, it works fine, but chrome wouldn't know the private key, so I think there's no need to set private key.
Does anyone know how to do? This question has tortured me very much!
I think to load private key you have to add to your code:
QByteArray keyData = customReadFile("/path/to/privatekey/PEM");
QSslKey sslPrivateKey(keyData, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, "PRIVATE KEY PASS");
conf.setPrivateKey(sslPrivateKey);
You have to implement customReadFile()
OS: Windows XP/Vista
Qt version: 4.6.1
Using OpenSSL
I need to watch the actual requests and responses that is going through the wire for QHttp requests and responses and in some cases need to interrupt the request. I tried with few of the http debuggers available in the market but they seem to work only for requests that are using the WinInet functions. Unfortunately, the openssldump utility is not present on windows platforms.
Thank you.
Wouldn't using QNetworkAccessManger instead of QHttp (which is obsolete) and reimplementing
QNetworkReply * QNetworkAccessManager::createRequest ( Operation op, const QNetworkRequest & req, QIODevice * outgoingData = 0 ) [virtual protected]
give you what you need?
Take a look at How to tell QWebPage not to load specific type of resources?. This is for QNAM used by QWebPage but it's the same for any code using QNAM.