如何使用Qt oauth创建登录页面?

时间:2018-01-25 23:26:23

标签: c++ qt oauth

当我的Qt桌面应用程序打开时,我一直在网上浏览如何创建身份验证页面。我已经构建了应用程序;这个很小,只有一个从main.cpp调用的MainWindow。

现在,我想在用户打开应用时添加身份验证页面。我创建了一个Google API(按照此链接的说明进行操作:http://blog.qt.io/blog/2017/01/25/connecting-qt-application-google-services-using-oauth-2-0/);但它真的不完整。在网上看,我无法找到一个链接,提供一个工作示例: - 用户运行应用程序并询问他的用户名和密码; - 如果它还没有存在,他可以创建一个。

我发现的所有内容都是不完整的代码,就像我上面分享的链接一样;或教程,显示如何创建具有硬编码密码和用户名的登录页面(这不是我想要的,我希望人们能够基于Google API动态添加自己)。

所以,如果某人有一小段代码要求用户提供用户名和密码,并且代码管理API的请求,那就太棒了!

编辑:添加我的代码

我添加了我的GoogleGateway课程代码(灵感来自我在此处找到的内容:How to set redirect_uri using QOAuth2AuthorizationCodeFlow and QOAuthHttpServerReplyHandler

GoogleGateway.h:

#ifndef GOOGLEGATEWAY_H
#define GOOGLEGATEWAY_H

#include <QObject>

class GoogleGateway : public QObject
{
    Q_OBJECT

public:
    GoogleGateway();
};

#endif // GOOGLEGATEWAY_H

GoogleGateway.cpp:

#include "googlegateway.h"
#include <QApplication>
#include <QObject>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QString>
#include <QFile>
#include <QUrl>
#include <QOAuth2AuthorizationCodeFlow>
#include <QOAuthHttpServerReplyHandler>
#include <QDesktopServices>

GoogleGateway::GoogleGateway() :
    QObject(){

auto google = new QOAuth2AuthorizationCodeFlow;
google->setScope("email");

this->connect(google, &QOAuth2AuthorizationCodeFlow::authorizeWithBrowser, &QDesktopServices::openUrl);

QString val;
QFile file;
file.setFileName("/.../auth.json");
file.open(QIODevice::ReadOnly | QIODevice::Text);
val = file.readAll();
file.close();

QJsonDocument document = QJsonDocument::fromJson(val.toUtf8());
QJsonObject object = document.object();
const auto settingsObject = object["web"].toObject();
const QUrl authUri(settingsObject["auth_uri"].toString());
const auto clientId = settingsObject["client_id"].toString();
const QUrl tokenUri(settingsObject["token_uri"].toString());
const auto clientSecret(settingsObject["client_secret"].toString());
const auto redirectUris = settingsObject["redirect_uris"].toArray();
const QUrl redirectUri(redirectUris[0].toString());
const auto port = static_cast<quint16>(redirectUri.port());

google->setAuthorizationUrl(authUri);
google->setClientIdentifier(clientId);
google->setAccessTokenUrl(tokenUri);
google->setClientIdentifierSharedKey(clientSecret);

auto replyHandler = new QOAuthHttpServerReplyHandler(port, this);
google->setReplyHandler(replyHandler);

google->grant();

}

现在,我需要在MainWindow.cpp中做些什么来提示将使用GoogleGateway类的登录页面? GoogleGateway这个类看起来不错吗?或者我需要修改一些东西吗?

另外,我在MainWindow构造函数中创建了一个类GoogleGateway的实例。当我运行代码时,它会在我的Chrome中打开一个网页标签,但会抛出错误400说“#34;错误:redirect_uri_mismatch&#34;”。这是什么意思?

感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

所以,Qt博客的文章几乎已经完成了。您只需要连接granted信号并在此之后发出所需的请求。

关于Qt博客中redirect_uri的/ cb路径的注释不再有效(文章大约一年前发布)。

  

注意:路径“/ cb”在当前是必需的   QOAuthHttpServerReplyHandler实现。

因此,如果您在运行代码后发现谷歌的访问错误,只需将redirect_uri从那里复制粘贴到您配置的客户端的GoogleConsole授权重定向URI即可。 http://localhost:8080/ &lt; - 不要忘记最后的斜线

enter image description here

P.S。:不要忘记再次使用控制台的凭据下载json文件。

此外,如果您想在授权后调用任何Google API,则需要在GoogleConsole中为您的项目启用它们。要测试代码,只需启用Google+ API

enter image description here

那就是它。这是完整且有效的代码。 (在Linux和Qt 5.10上测试过,目前还没有Windows,无法在那里测试)

<强> googlegateway.h

#ifndef GOOGLEGATEWAY_H
#define GOOGLEGATEWAY_H

#include <QObject>
#include <QOAuth2AuthorizationCodeFlow>
#include <QNetworkReply>

class GoogleGateway : public QObject
{
    Q_OBJECT
public:
    explicit GoogleGateway(QObject *parent = nullptr);

private:
    QOAuth2AuthorizationCodeFlow * google;
};

#endif // GOOGLEGATEWAY_H

<强> googlegateway.cpp

#include "googlegateway.h"
#include <QObject>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QString>
#include <QFile>
#include <QDir>
#include <QUrl>
#include <QOAuthHttpServerReplyHandler>
#include <QDesktopServices>


GoogleGateway::GoogleGateway(QObject *parent) : QObject(parent)
{
    this->google = new QOAuth2AuthorizationCodeFlow(this);
    this->google->setScope("email");

    connect(this->google, &QOAuth2AuthorizationCodeFlow::authorizeWithBrowser, &QDesktopServices::openUrl);

    QByteArray val;
    QFile file;
    file.setFileName(QDir::toNativeSeparators("/full/path/client_secret_XXXXXXX.apps.googleusercontent.com.json"));
    if(file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        val = file.readAll();
        file.close();
    }


    QJsonDocument document = QJsonDocument::fromJson(val);
    QJsonObject object = document.object();
    const auto settingsObject = object["web"].toObject();
    const QUrl authUri(settingsObject["auth_uri"].toString());
    const auto clientId = settingsObject["client_id"].toString();
    const QUrl tokenUri(settingsObject["token_uri"].toString());
    const auto clientSecret(settingsObject["client_secret"].toString());

    const auto redirectUris = settingsObject["redirect_uris"].toArray();
    const QUrl redirectUri(redirectUris[0].toString());
    const auto port = static_cast<quint16>(redirectUri.port());

    this->google->setAuthorizationUrl(authUri);
    this->google->setClientIdentifier(clientId);
    this->google->setAccessTokenUrl(tokenUri);
    this->google->setClientIdentifierSharedKey(clientSecret);

    auto replyHandler = new QOAuthHttpServerReplyHandler(port, this);
    this->google->setReplyHandler(replyHandler);
    this->google->grant();

    connect(this->google, &QOAuth2AuthorizationCodeFlow::granted, [=](){
        qDebug() << __FUNCTION__ << __LINE__ << "Access Granted!";
        auto reply = this->google->get(QUrl("https://www.googleapis.com/plus/v1/people/me"));
        connect(reply, &QNetworkReply::finished, [reply](){
            qDebug() << "REQUEST FINISHED. Error? " << (reply->error() != QNetworkReply::NoError);
            qDebug() << reply->readAll();
        });
    });
}

答案 1 :(得分:0)

请记住,将所有本地主机的Google控制台中的重定向URI设置为http://127.0.0.1:port_no/,而不是http://localhost:port_no/

请记住将尾部的'/'放入重定向URI。

其余代码

this->google = new QOAuth2AuthorizationCodeFlow(this);
        this->google->setScope("email");

        connect(this->google, &QOAuth2AuthorizationCodeFlow::authorizeWithBrowser, &QDesktopServices::openUrl);

        this->google->setAuthorizationUrl(QUrl("https://accounts.google.com/o/oauth2/auth"));
        this->google->setClientIdentifier(MY_CLIENT_ID);
        this->google->setAccessTokenUrl(QUrl("https://oauth2.googleapis.com/token"));
        this->google->setClientIdentifierSharedKey(MYTOKEN);

// In my case, I have hardcoded 8080 to test
        auto replyHandler = new QOAuthHttpServerReplyHandler(8080, this);
        this->google->setReplyHandler(replyHandler);
        this->google->grant();

        qDebug() << "Access";

        connect(this->google, &QOAuth2AuthorizationCodeFlow::granted, [=](){
            qDebug() << __FUNCTION__ << __LINE__ << "Access Granted!";

            auto reply = this->google->get(QUrl("https://www.googleapis.com/plus/v1/people/me"));
            connect(reply, &QNetworkReply::finished, [reply](){
                qDebug() << "REQUEST FINISHED. Error? " << (reply->error() != QNetworkReply::NoError);
                qDebug() << reply->readAll();
            });
        });