为什么我收到来自Google的错误请求?

时间:2018-10-03 08:47:05

标签: c++ qt google-drive-api qt5

我的目标
使用OAuth 2将刷新令牌与Google的访问令牌交换。

我的代码

bool Google_Account::Refresh_Access_Token_Using_Refresh_Token()
{  
    // Prepare Url
    QUrl url(tr("https://www.googleapis.com/oauth2/v4/token"));

    // Create request
    QNetworkRequest request(url);
    request.setRawHeader("Host:","www.googleapis.com");
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");

    // Create request body ClientID, ClientSecret, RefreshTokenString are class data members
    QString RequestBody = tr("client_secret=%1&").arg(ClientSecret) +
                          tr("grant_type=refresh_token&")+
                        tr("refresh_token=%1&").arg(RefreshTokenString)+
                          tr("client_id=%1").arg(ClientID);

    QByteArray array = RequestBody.toUtf8();

    // Get reply
    QNetworkReply *reply = mQNAM.post(request, array); // mQNAM is QNetworkAccessManager

    // Set timeout to reply while waiting for reply finished
    bool stop = false;
    QTimer timer;
    timer.setSingleShot(true);

    QObject::connect(&timer, &QTimer::timeout, [&](){
        qDebug()<<"Time out";
        stop = true;
    });
    timer.start(5000);

    // Wait till the response is completed
    while(!reply->isFinished()){
        QCoreApplication::processEvents();
        if(stop){
            qDebug()<<"Going to abort";
            reply->abort();
        }
    }

    // Check for reply
    if(reply->isFinished()){

        if(reply->error() != QNetworkReply::NoError){
            qDebug()<<reply->readAll();
            emit setMessage("Error: "+reply->errorString());
            delete reply;
            return false;
        }
        else{
            QByteArray array = reply->readAll();
            QJsonDocument document = QJsonDocument::fromJson(array);
            QJsonObject obj = document.object();
            access_token = obj.value("access_token").toString(); //access_token is class data variable
            delete reply;
            return true;
        }
    }
    else{
        delete reply;
        return false;
    }
}

问题是,如果我在Windows 7 pc(Qt 5.11.1)中运行此代码,一切都很好,我会获得访问令牌,但如果我在树莓派(raspbian Qt 5.7)中运行,则会出现错误400,错误来自Google的请求。我尝试使用从Windows PC上获得的access_token并发出其他请求,例如从Google驱动器获取文件列表,它们在树莓派中工作正常,但是只有这个我有问题。我究竟做错了什么? P.S该代码仅重构为特定细节,实际上我是从QSettings获取客户端ID和其他密钥的

1 个答案:

答案 0 :(得分:0)

这听起来像是在 Qt 请求令牌时收到 400 代码,因为当流程返回到您的应用程序时您获得的登录代码是 URL 编码的。我们用一些代码示例编写了关于 How To Authenticate with Google SSO in Qt 的内容,包括在流程中注入参数修饰符的这一位:

google->setModifyParametersFunction([](QAbstractOAuth::Stage stage, QVariantMap* parameters) {
   // Percent-decode the "code" parameter so Google can match it
   if (stage == QAbstractOAuth::Stage::RequestingAccessToken) {
      QByteArray code = parameters->value("code").toByteArray();
      (*parameters)["code"] = QUrl::fromPercentEncoding(code);
   }
});

在初始请求之前执行此操作,但正如上面@Giancarlo 所建议的那样,我会重写您的代码以异步工作。它更简单、更可靠。