QNetworkAccessManager摘要认证实现咨询:手动计算MD5后设置请求头的方式是否正确
QNetworkAccessManager 摘要认证手动实现问题解答
首先明确说:手动计算MD5来发起摘要认证请求是完全可行的。Qt的QNetworkAccessManager并没有强制要求必须用它内置的认证机制,只要你严格遵循HTTP摘要认证的规范生成所有必要参数,自定义请求头的方式完全能完成认证流程。
不过看你的代码,这里有个关键的错误需要修正:你把Digest认证的各个参数拆分成了多个独立的请求头,但HTTP规范里要求所有Digest相关参数都要放在同一个Authorization请求头里,格式是这样的:
Authorization: Digest username="xxx", realm="xxx", nonce="xxx", uri="xxx", algorithm=MD5, response="xxx", qop="xxx", nc=xxx, cnonce="xxx"
你当前的写法会让服务器无法识别这些分散的头信息,自然无法完成认证。下面是修正后的代码片段:
QString G_username = QString::fromUtf8(_userName.c_str()); QString G_realm = QString::fromUtf8(_realm.c_str()); QString G_nonce = QString::fromUtf8(_nonce.c_str()); QString G_uri = QString::fromUtf8(urlAfterIp.c_str()); QString G_response = QString::fromUtf8(ha3.c_str()); QString G_qop = QString::fromUtf8(_qop.c_str()); QString G_nc = QString::fromUtf8((_ncString).c_str()); QString G_cnonce = QString::fromUtf8(_cnonce.c_str()); QEventLoop loop; QNetworkAccessManager* manager = new QNetworkAccessManager(); QNetworkRequest networkRequest; networkRequest.setUrl(QUrl("http://172.16.101.68/reset")); // 拼接完整的Digest认证头 QString digestAuthHeader = QString("Digest username=\"%1\", realm=\"%2\", nonce=\"%3\", uri=\"%4\", algorithm=MD5, response=\"%5\", qop=\"%6\", nc=%7, cnonce=\"%8\"") .arg(G_username, G_realm, G_nonce, G_uri, G_response, G_qop, G_nc, G_cnonce); // 设置唯一的Authorization头 networkRequest.setRawHeader(QByteArray("Authorization"), digestAuthHeader.toUtf8()); QLabel *label = new QLabel(); QNetworkReply *reply = manager->get(networkRequest); // 后面的信号连接和事件循环逻辑保持不变... QObject::connect(reply, SIGNAL(readyRead()), label, SLOT(slotReadyRead())); QObject::connect(reply, SIGNAL(finished()), label, SLOT(slotOnRequestCompleted())); QObject::connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), label, SLOT(slotOnRequestError(QNetworkReply::NetworkError))); QObject::connect(reply, SIGNAL(sslErrors(QList<QSslError>)), label, SLOT(slotSslErrors(QList<QSslError>))); QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit())); loop.exec(); QByteArray dataReceived = reply->readAll(); QString dataReply(dataReceived);
另外再补充几个需要注意的点:
- 一定要确保
G_response(也就是HA3)的计算完全符合规范:当qop为auth时,HA3 = MD5(HA1:nonce:nc:cnonce:qop:HA2),其中HA1=MD5(username:realm:password),HA2=MD5(GET:/reset)(这里的方法和URI要和实际请求一致) - 注意参数的引号:像username、realm、nonce这类字符串参数必须用双引号包裹,而nc(nonce计数)是数字,不需要引号
- 其实Qt本身提供了
QAuthenticator类,可以通过QNetworkAccessManager::authenticationRequired信号来处理认证,这种方式更符合Qt的设计模式,也能避免手动计算的失误,但如果你的场景必须手动处理,修正后的头设置方式是正确的
内容的提问来源于stack exchange,提问作者user4165962
相关产品推荐
相关产品推荐

