Qt 5.7 QNetworkProxy не учитывает куки

Я работаю над клиентским приложением Qt cloud, которое использует QWebEngineView и QNetworkAccessManager. Проблема, с которой я столкнулся, описана ниже:

Приложение имеет настраиваемую форму входа в систему. Основываясь на учетных данных пользователей, я выполняю серию ручных запросов («публикация» и «получение») для получения соответствующих файлов cookie сеанса.

    ...
//get session cookie
QNetworkAccessManager accessManager;
connect(&accessManager, &QNetworkAccessManager::proxyAuthenticationRequired, [=] (const QNetworkProxy &proxy, QAuthenticator *authenticator){
//perform proxy auth in case a proxy is set
});

QNetworkReply * reply = Q_NULLPTR;

QNetworkRequest request(QUrl(/*url*/));
request.setRawHeader("Content-Type", "application/x-www-form-urlencoded");
request.setRawHeader("Cache-Control", "no-cache");

QByteArray data(/*data for auth*/);
reply = accessManager.post(request,data); //ajax login

QEventLoop waitReplyHandler;
QObject::connect(reply, SIGNAL(finished()), &waitReplyHandler, SLOT(quit()));

//wait for reply from url
waitReplyHandler.exec();
QVariant sessionCookie = reply->header(QNetworkRequest::SetCookieHeader); //this cookie is used to retrieve second "session cookie"...

//Different function - get user session cookie
QNetworkRequest request(QUrl(/*url*/));

request.setHeader(QNetworkRequest::CookieHeader, sessionCookie);
QNetworkReply * reply = accessManager.get(request);

QEventLoop waitReplyHandler;
QObject::connect(reply, SIGNAL(finished()), &waitReplyHandler, SLOT(quit()));

//wait for reply from url
waitReplyHandler.exec();
QString redirect = reply->header(QNetworkRequest::LocationHeader).toString();
QVariant userSessionCookie = reply->header(QNetworkRequest::SetCookieHeader);

После этого я установил перехватчик запросов для QWebEngineView:

    interceptor = new CWebEngineUrlRequestInterceptor(sessionCookie.value<QList<QNetworkCookie>>().first(),
userSessionCookie.value<QList<QNetworkCookie>>().first(),
this);
m_tabWebview->webEngineView()->page()->profile()->setRequestInterceptor(interceptor);
m_tabWebview->webEngineView()->load(redirectUrl); //Obtained from "redirect" string variable from second manual request

Идея состоит в том, чтобы использовать эти полученные вручную файлы cookie для каждого вызова загрузки для просмотра веб-движка:

    void CWebEngineUrlRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo &info)
{
QByteArray sessionCookie = QByteArray(m_sessionCookie.name() + "=" + m_sessionCookie.value());
QByteArray userSessionCookie = QByteArray(m_userSessionCookie.name() + "=" + m_userSessionCookie.value());

QByteArray requestCookies = sessionCookie + "; " + userSessionCookie;

info.setHttpHeader(QByteArray("Cookie"), requestCookies);
}

Это прекрасно работает, после загрузки в redirectUrl, в веб-представлении будет отображаться домашняя страница облака с уже зарегистрированным пользователем. Однако, если я установлю QNetworkProxy для приложения:

    QNetworkProxy proxy;
proxy.setType(QNetworkProxy::HttpProxy);
proxy.setHostName(proxyUrl);
proxy.setPort(proxyPort.toInt());

QNetworkProxy::setApplicationProxy(proxy);

Приведенная выше последовательность будет отображаться на веб-странице входа моей целевой ссылки. Я считаю, что настройки прокси на уровне приложения не должны зависеть от QWebEngineView. Ручные запросы работают, я могу получить файлы cookie, также вызывается запрос interceptRequest, но файлы cookie не сохраняются после ретрансляции прокси.
Я также попытался вручную установить заголовок для самого прокси:

    QByteArray requestCookies = m_cookies.first().name() + "=" + m_cookies.first().value() + "; " +
m_cookies.last().name() + "=" + m_cookies.last().value();

QNetworkProxy proxy(QNetworkProxy::applicationProxy());
proxy.setRawHeader(QByteArray("Cookie"), requestCookies);
QNetworkProxy::setApplicationProxy(proxy);
//...
//check headers are set to proxy
QByteArray cookieVar = QNetworkProxy::applicationProxy().rawHeader(QByteArray("Cookie"));
if(cookieVar.isEmpty()){
std::cout<<"empty cookies to proxy ";
}
else{
std::cout<<cookieVar.toStdString()<<std::endl;
}

Журналы в порядке, я вижу, что куки прикреплены к прокси.

Этот пользовательский механизм входа в систему реализован для обработки автоматического входа в случае, если нет подключения к Интернету в течение более длительного периода времени, чем время истечения сеансового cookie.
Как настроить прокси уровня приложения для использования сессионных файлов cookie, полученных вручную?

Заранее спасибо.

1

Решение

Кажется, это ошибка в структуре веб-движка, связанная с механизмом аутентификации прокси. Однако я нашел обходной путь:
Когда вызывается QWebEnginePage :: proxyAuthenticationRequired, после того как данные объекта аутентификатора установлены, я просто снова вызываю load для параметра requestUrl.

connect(app->webview()->page(), &QWebEnginePage::proxyAuthenticationRequired, [=] (const QUrl &requestUrl, QAuthenticator *authenticator, const QString &proxyHost){
proxyAuthSequence(authenticator, proxyHost);
app->webview()->load(requestUrl);
});

Идея состоит в том, чтобы рассматривать начальную загрузку как фиктивную загрузку только для установки данных аутентификации, а затем снова загружать URL-адрес. Последующие вызовы загрузки больше не будут вызывать этот сигнал. Итак, в основном проблема с механизмом аутентификации.

Ошибка также была отправлена ​​в Qt:
https://bugreports.qt.io/browse/QTBUG-58121

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]