有没有办法在PyQt4中强制使用QNetworkAccessManager进行身份验证?
问题描述:
在我的实现中,似乎QNetworkAccessManager
在成功验证后缓存用于特定URL的凭证。有没有办法在PyQt4中强制使用QNetworkAccessManager进行身份验证?
随后请求使用不同凭据会成功相同的URL,但仅仅是因为它使用了缓存的凭据,而不是新的(在authenticationRequired
信号未发出)。
(Py)Qt4中是否有某种方式清除缓存或以其他方式强制更新缓存的凭据?我应该删除经理并构建一个新的?还是有什么我做错了?据我所知,Qt 5提供了一个clearAccessCache()
方法,但是Qt 4没有。
这个小例子说明了这个问题:
import sys
import json
from PyQt4 import QtNetwork, QtGui, QtCore
def show_reply_content(reply):
content = json.loads(str(reply.readAll()))
if 'authenticated' in content and content['authenticated']:
print 'authentication successful for user {}'.format(
content['user'])
reply.manager().replies_authenticated += 1
# Quit when all replies are finished
reply.deleteLater()
reply.manager().replies_unfinished -= 1
if not reply.manager().replies_unfinished:
print 'number of successful authentications: {}'.format(
reply.manager().replies_authenticated)
app.quit()
def provide_credentials(reply, authenticator):
print 'Setting credentials for {}:\nusername: {}\n' \
'password: {}\n\n'.format(reply.url(),
reply.credentials['username'],
reply.credentials['password'])
authenticator.setUser(reply.credentials['username'])
authenticator.setPassword(reply.credentials['password'])
# Some initialization
app = QtGui.QApplication(sys.argv)
manager = QtNetwork.QNetworkAccessManager()
manager.finished.connect(show_reply_content)
manager.authenticationRequired.connect(provide_credentials)
manager.replies_unfinished = 0
manager.replies_authenticated = 0
# Specify credentials
all_credentials = [dict(username='aap',
password='njkrfnq'),
dict(username='noot',
password='asdfber')]
# url authenticates successfully only for the specified credentials
url = 'http://httpbin.org/basic-auth/{}/{}'.format(
*all_credentials[1].values())
# Schedule requests
replies = []
for credentials in all_credentials:
replies.append(
manager.get(QtNetwork.QNetworkRequest(QtCore.QUrl(url))))
# Add credentials as dynamic attribute
replies[-1].credentials = credentials
manager.replies_unfinished += 1
# Start event loop
app.exec_()
只要有一个请求被成功验证,下一个是为好,尽管它不应该。
答
事实证明也有几个类似的Qt的bug报告仍然打开:QTBUG-16835,QTBUG-30433 ...
我想这应该是可以使用QNetworkRequest.AuthenticationReuseAttribute
,但我不能让与多个请求的工作与具有不同(有效)证书集的相同url。
可能的解决方法是忘记所有关于authenticationRequired
信号/插槽,并向每个请求添加原始标头(RFC 7617),确切地说是as described here。
在这将意味着去除authenticationRequired
信号/槽连接,并通过下面的线路(对于Python 2.7使用PyQt4的)替换manager.get()
部分的例子:
request = QtNetwork.QNetworkRequest(QtCore.QUrl(url))
header_data = QtCore.QByteArray('{}:{}'.format(
credentials['username'], credentials['password'])).toBase64()
request.setRawHeader('Authorization', 'Basic {}'.format(header_data))
replies.append(manager.get(request))
然而,如@ekhumoro在指出上面的评论:不知道这是多么安全。
你使用的是什么特定版本的Qt4?这个错误看起来很相似:[QTBUG-15566](https://bugreports.qt.io/browse/QTBUG-15566)。 – ekhumoro
也有关:[QNetworkAccessManager - 如何执行身份验证?](http://thread.gmane.org/gmane.comp.lib.qt.user/3141) – ekhumoro
不确定Qt版本,但我使用的是PyQt4 .11.4。我仍然需要查看该错误报告,但第二个链接指向'QNetworkRequest.AuthenticationReuseAttribute',这听起来很有希望。不幸的是,我的第一次尝试,使用'request.setAttribute(QNetworkRequest.AuthenticationReuseAttribute,QNetworkRequest.Manual)',不起作用:现在所有的请求都被401拒绝。我稍后会介绍这一点。 – Dennis