我正在尝试进行身份验证以访问 Clio API。在 Windows 中使用 Qt 5.15.2。
当前的源代码可以在我的电脑上运行。我可以使用经过身份验证的 QOAuth2AuthorizationCodeFlow 对象来请求 API 方法。稍后再详细介绍。
这是类声明:
#include <QtCore>
#include <QObject>
#include <QMessageBox>
#include <QNetworkReply>
#include <QDesktopServices>
#include <QOAuth2AuthorizationCodeFlow>
#include <QOAuthHttpServerReplyHandler>
class ClioAuth:public QObject {
Q_OBJECT
public:
ClioAuth(QObject * =nullptr);
~ClioAuth();
void authorize();
void setAuthParams(QString,QString,QString,QString,QString,QString);
QVariantMap Tokens();
QOAuth2AuthorizationCodeFlow *OAuth();
private:
QString sScope,
sAuthURL,
sClientId,
sSharedKey,
sTokenURL,
sRedirectURL;
QVariantMap vmpTokens;
QOAuth2AuthorizationCodeFlow *oa2OAuth;
QOAuthHttpServerReplyHandler *oa2Reply;
signals:
void authError(QString,QString,QString);
void authSuccess();
};
这是类定义:
#include "clioauth.h"
ClioAuth::ClioAuth(QObject *objParent):QObject(objParent) {
sScope.clear();
sAuthURL.clear();
sClientId.clear();
sSharedKey.clear();
sTokenURL.clear();
sRedirectURL.clear();
vmpTokens.clear();
oa2OAuth=new QOAuth2AuthorizationCodeFlow(objParent);
QObject::connect(oa2OAuth,
&QOAuth2AuthorizationCodeFlow::error,
this,
[=](QString sError,QString sDescription,QUrl urlError) {
emit authError(sError,sDescription,urlError.toString());
});
QObject::connect(oa2OAuth,
&QOAuth2AuthorizationCodeFlow::statusChanged,
this,
[=](QAbstractOAuth::Status status) {
if(QAbstractOAuth::Status::Granted==status)
emit authSuccess();
});
QObject::connect(oa2OAuth,
&QOAuth2AuthorizationCodeFlow::authorizeWithBrowser,
&QDesktopServices::openUrl);
oa2Reply=new QOAuthHttpServerReplyHandler(objParent);
QObject::connect(oa2Reply,
&QOAuthHttpServerReplyHandler::tokensReceived,
this,
[this](QVariantMap vmpParams) {
vmpTokens=vmpParams;
});
}
ClioAuth::~ClioAuth() {
delete oa2OAuth;
delete oa2Reply;
}
void ClioAuth::authorize() {
oa2OAuth->setScope(sScope);
oa2OAuth->setAuthorizationUrl(QUrl(sAuthURL));
oa2OAuth->setClientIdentifier(sClientId);
oa2OAuth->setAccessTokenUrl(QUrl(sTokenURL));
oa2OAuth->setClientIdentifierSharedKey(sSharedKey);
oa2OAuth->setReplyHandler(oa2Reply);
oa2OAuth->setModifyParametersFunction(
[this](QAbstractOAuth::Stage,QVariantMap *vmpParams) {
(*vmpParams)[QStringLiteral("redirect_uri")]=
QStringLiteral("http://127.0.0.1:%1").arg(oa2Reply->port());
});
oa2OAuth->grant();
}
void ClioAuth::setAuthParams(QString sNewScope,QString sNewAuthURL,
QString sNewClientId,QString sNewSharedKey,
QString sNewTokenURL,QString sNewRedirectURL) {
sScope=sNewScope;
sAuthURL=sNewAuthURL;
sClientId=sNewClientId;
sSharedKey=sNewSharedKey;
sTokenURL=sNewTokenURL;
sRedirectURL=sNewRedirectURL;
}
QVariantMap ClioAuth::Tokens() {
return vmpTokens;
}
QOAuth2AuthorizationCodeFlow *ClioAuth::OAuth() {
return oa2OAuth;
}
如您所见,我基本上忽略了重定向 URL 并使用 127.0.0.1:XXXXX,其中 XXXXX 是分配的 QOAuthHttpServerReplyHandler 决定绑定和侦听的任何端口。
我正在使用这样的类:
caClio->setAuthParams(QStringLiteral(CLIO_SCOPE_ALL),
QStringLiteral(CLIO_URL_AUTH),
QStringLiteral(CLIO_APP_KEY),
QStringLiteral(CLIO_APP_SECRET),
QStringLiteral(CLIO_URL_TOKEN),
QStringLiteral(CLIO_URL_APPROVAL));
connect(caClio,SIGNAL(authSuccess()),this,SLOT(on_authSuccess()));
caClio->authorize();
现在,调用 caClio->authorize() 后,默认浏览器打开,然后我按照那里的授权过程,最终重定向到http://127.0.0.1:XXXXX/?code=ZA0EekH9zL0hJt5WcOYs&state=dpfEqPxM(代码和状态不同每次,当然)并显示通常的消息:收到回调。随意关闭此页面。
到目前为止,对于我的 PC 和客户的 PC,一切都一样。
在我的 PC 中,达到了 on_authSuccess()。我什至可以像这样显示授权令牌:
if(!caClio->Tokens().empty()) {
QMapIterator<QString,QVariant> i(caClio->Tokens());
while(i.hasNext()) {
i.next();
qDebug() << QStringLiteral("%1: %2").arg(i.key(),i.value().toString());
}
}
但是在我客户的 PC(我没有本地访问权限,顺便说一句)中,没有达到 on_authSuccess(),我不知道为什么。
关于我应该做什么的任何建议?
最后的一些细节:
- 没有防火墙相关的问题。客户也会在他们的浏览器中收到“收到回调”消息。
- 在我的 PC 中到达 on_authSuccess() 后,Qt Creator 的应用程序输出显示以下调试消息:qt.networkauth.oauth2 : Unexpected call(我无法弄清楚原因,但它也不影响授予状态)。