0

我正在尝试进行身份验证以访问 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(我无法弄清楚原因,但它也不影响授予状态)。
4

0 回答 0