Details
-
Bug
-
Resolution: Done
-
P2: Important
-
5.9.1, 5.9
-
None
-
8b64a1054ab5a428b7fcc4efad3ff31bc55dd7ed
Description
Problem
If QNetworkRequest::FollowRedirectsAttribute is set to true in the request and/or QNetworkRequest::RedirectPolicy is set to a value different than QNetworkRequest::ManualRedirectPolicy, it actually follow the redirect but ignores all the cookies received in the redirection process.
Example
Example with a django application to which I tried to login using basic-auth:
The workflow works like that:
- client requests /admin/ -> server replies 302 and redirects to /admin/login/
- clients follow redirects and requets /admin/login/ -> server replies 401 asking for basic auth
- clients requests /admin/login/ and sends credentials -> server sets cookie sessionid, replies 302 and redirects to /admin/
- clients requests /admin/ and sends sessionid cookie -> server reads sessionid and replies with 200
If i follow this procedure with the browser or with the requests module in python it works like a charm.
If I try with the code below the server does't receive any cookie, they are always empty, and the client enters in a redirect loop.
SsoNetworkManager::SsoNetworkManager(QObject *parent) : QNetworkAccessManager(parent) { connect(this, SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*)), this, SLOT(onAuthenticationRequired(QNetworkReply*,QAuthenticator*))); connect(this, SIGNAL(finished(QNetworkReply*)), this, SLOT(onFinished(QNetworkReply*))); } void SsoNetworkManager::onAuthenticationRequired(QNetworkReply *reply, QAuthenticator *auth) { auth->setUser(QString("test")); auth->setPassword(QString("test")); } void SsoNetworkManager::onFinished(QNetworkReply *reply) { qDebug() << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); } ... SsoNetworkManager nam; QNetworkRequest request("http://127.0.0.1:8000/admin/"); request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); nam.get(request); ...
I just tried to remove the QNetworkRequest::FollowRedirectsAttribute and manually handle the redirects. This way it stores the cookies.
Hints (maybe)
I investigated further and took a look at the source code.
qnetworkaccessmanager.cpp
to set cookies QNetworkAccessManager uses
request.setHeader(QNetworkRequest::CookieHeader, QVariant::fromValue(cookies));
Anyway the QNetworkAccessManager uses the CookieJar only inside this method:
QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest &originalReq, QIODevice *outgoingData) { //... }
Which is only called by the public methods "head, get, post, put, deleteResources and sendCustomRequest" which are not called to send the redirected requests.
They are internally handled, the redirection process is completely transparent to the QNetworkAccessManager.
qnetworkreplyhttpimpl.cpp
It looks like that when a redirect request is created it just take care of copying the original request changing the url, it doesn't take into account any other information got from the response.
QNetworkRequest QNetworkReplyHttpImplPrivate::createRedirectRequest(const QNetworkRequest &originalRequest, const QUrl &url, int maxRedirectsRemaining) { QNetworkRequest newRequest(originalRequest); newRequest.setUrl(url); newRequest.setMaximumRedirectsAllowed(maxRedirectsRemaining); return newRequest; }
Hope it helps.
Attachments
Issue Links
- is required for
-
QTBUG-63438 Improve (or even implement) the correct redirects support
-
- Closed
-
For Gerrit Dashboard: QTBUG-63313 | ||||||
---|---|---|---|---|---|---|
# | Subject | Branch | Project | Status | CR | V |
207042,6 | Fix cookies not being applied on redirect | 5.9 | qt/qtbase | Status: MERGED | +2 | 0 |