Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 有没有办法在PyQt4/5中强制使用QNetworkAccessManager进行身份验证?_Python_Qt_Pyqt_Pyqt4_Qnetworkaccessmanager - Fatal编程技术网

Python 有没有办法在PyQt4/5中强制使用QNetworkAccessManager进行身份验证?

Python 有没有办法在PyQt4/5中强制使用QNetworkAccessManager进行身份验证?,python,qt,pyqt,pyqt4,qnetworkaccessmanager,Python,Qt,Pyqt,Pyqt4,Qnetworkaccessmanager,在我的实现中,似乎QNetworkAccessManager在成功身份验证后缓存了用于特定url的凭据 使用不同凭据对同一url的后续请求将成功,但这只是因为它使用缓存的凭据而不是新凭据(不会发出authenticationRequired信号) (Py)Qt4(也是pyqt5.6)中是否有办法清除缓存或强制更新缓存的凭据?我是否应该删除管理器并构建一个新的管理器?或者是我做错了什么 Qt5提供了一个clearAccessCache()方法,但据我所知,Qt4没有 这个小例子说明了问题: imp

在我的实现中,似乎
QNetworkAccessManager
在成功身份验证后缓存了用于特定url的凭据

使用不同凭据对同一url的后续请求将成功,但这只是因为它使用缓存的凭据而不是新凭据(不会发出
authenticationRequired
信号)

(Py)Qt4(也是pyqt5.6)中是否有办法清除缓存或强制更新缓存的凭据?我是否应该删除管理器并构建一个新的管理器?或者是我做错了什么

Qt5提供了一个
clearAccessCache()
方法,但据我所知,Qt4没有

这个小例子说明了问题:

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错误报告仍然存在:

我想应该可以使用
QNetworkRequest.AuthenticationReuseAttribute
,但我无法使用多个对同一url的请求以及不同(有效)的凭据集

一种可能的解决方法是完全忘记
authenticationRequired
signal/slot,在每个请求中添加一个原始头()

在本例中,这意味着删除
authenticationRequired
信号/插槽连接,并用以下行替换
manager.get()
部分(对于PyQt4的Python 2.7):


然而,正如@ekhumoro在上面的评论中指出的那样:不确定这有多安全。

您使用的Qt4的具体版本是什么?这个bug看起来很相似:。同样相关:不确定Qt版本,但我使用的是PyQt4.11.4。我仍然需要查看那个bug报告,但是第二个链接指向了
QNetworkRequest.AuthenticationReuseAttribute
,这听起来很有希望。不幸的是,我第一次尝试使用
request.setAttribute(QNetworkRequest.AuthenticationReuseAttribute,QNetworkRequest.Manual)
,没有成功:现在所有请求都被401拒绝。我稍后会深入讨论这个问题。@ekhumoro,上面提到的错误看起来确实很相似,因为使用了缓存的凭据。但是当我使用PyQt5.6时,这种行为仍然存在。使用WIreshark进行的快速检查表明,一旦找到一组有效的凭证(如状态200所示),这些凭证将用于对该url的任何后续请求,以及任何未决请求(只要他们收到401,经理就会继续发送这些凭证),而
authorizationRequired
信号不会再次发出,直到向另一个url(也需要授权)发出请求。也许该怎么办?
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))