本页内容

Qt 对 OAuth2 浏览器的支持

OAuth2 用户代理

OAuth2授权阶段 依赖于用户代理,通常是系统浏览器或嵌入式用户代理,例如 Qt WebEngine。

选择系统浏览器还是嵌入式用户代理取决于多个因素。以下描述了几个主要考虑因素:

  • 系统浏览器中可能已有用户的活跃登录会话。 因此,授权阶段的用户身份验证可能更为简便,因为可以利用现有的登录会话。相比之下,使用嵌入式用户代理时,用户通常需要重新登录。另一方面,在系统浏览器中保留登录会话未必总是可取的。系统浏览器还可能与其他方共享应用程序使用数据。
  • 系统浏览器通常对用户而言较为熟悉,并能提供熟悉的登录体验。 另一方面,尽管嵌入式用户代理的外观和操作体验可能不太熟悉,但应用程序开发人员能够将登录交互嵌入到应用程序窗口中,而不是在单独的浏览器窗口中进行。此外,当不再需要时,应用程序开发人员可以自动关闭嵌入式用户代理。
  • 系统浏览器为用户提供熟悉的安全视觉元素,例如地址栏和证书验证。这些元素在嵌入式用户代理中可能不可见。此外,系统浏览器可能更好地利用底层操作系统的安全功能。
  • 嵌入式用户代理可能能够访问用户输入的所有安全凭据。
  • 并非所有平台都支持处理https 或自定义 URI 方案的重定向 URL(参见QOAuthUriSchemeReplyHandler )。在这些平台上,可使用嵌入式用户代理来规避此限制。
  • 将嵌入式用户代理作为应用程序的一部分通常会增加其体积,从而扩大应用程序的存储占用空间。另一方面,并非所有使用场景都可使用系统浏览器,或者应用程序可能已出于其他目的使用了嵌入式用户代理。

考虑到这些因素,建议原生应用使用系统浏览器。但正如上文某些要点所暗示的,使用嵌入式用户代理仍可能存在合理的使用场景。

使用系统浏览器

使用系统浏览器需要先将其打开,然后导航至应用程序配置的授权 URL。典型用法如下:

connect(&m_oauth, &QAbstractOAuth::authorizeWithBrowser, this, &QDesktopServices::openUrl);

该代码将QAbstractOAuth::authorizeWithBrowser 信号与QDesktopServices::openUrl 槽进行连接。这将打开系统浏览器,用户可在其中完成必要的身份验证和授权。应用程序或 Qt 库无法直接控制系统浏览器,且授权完成后,系统浏览器通常会保持打开状态。

有关系统浏览器的更多详细信息及支持的重定向 URL 方案,请参阅《OAuth 2.0 概述》、QOAuthHttpServerReplyHandler 以及QOAuthUriSchemeReplyHandler 。

使用Qt WebEngine

Qt WebEngine 提供了一个 Web 浏览器引擎,可将 Web 内容直接嵌入到 Qt 应用程序中。

除了核心控制功能外,它还为 QtWidgets 和 QtQuick 应用程序提供了易于使用的视图。这些视图可作为 OAuth2 授权中的用户代理。 Qt WebEngine 是一个功能强大且用途广泛的模块,本文档的重点在于将其与 OAuth2 授权结合使用。

将Qt WebEngine 作为应用程序的一部分进行嵌入的方法有很多。从实际角度来看,主要需要考虑以下几点:

  • QtQuick 与 QtWidgets 应用程序的区别。这会影响如何与QtNetworkAuth 类建立必要的集成。
  • 重定向 URI 方案。这会影响应使用哪些QtNetworkAuth 响应处理程序类,以及如何使用(参见《OAuth 2.0 概述》)。

QtQuick 和 QtWidgets 应用程序

Qt WebEngine 均可用于 QtQuick 和 QtWidgets 应用程序的 OAuth 2.0 授权。主要区别在于如何配置少数必要的启用组件。

下文展示了一个简化的QWebEngineView (QtWidgets)配置示例。出于篇幅考虑,错误处理及任何潜在的 Qt WebEngine 配置均被省略。

假设使用以下控件:

QWebEngineView *webView = nullptr;
QMainWindow mainWindow;

我们不打开系统浏览器,而是使用QWebEngineView 来执行授权:

connect(&m_oauth, &QAbstractOAuth::authorizeWithBrowser, this, [this](const QUrl &url) {
    mainWindow.show();
    webView->load(url);
    webView->show();
});

授权完成后,关闭视图:

connect(&m_oauth, &QAbstractOAuth::granted, this, [this]() {
    // Here we use QNetworkRequestFactory to store the access token
    m_api.setBearerToken(m_oauth.token().toLatin1());
    m_handler->close();
    webView->close();
});

对于 QtQuick 应用程序,流程原则上相同,但我们使用WebEngineView QML 元素代替QWebEngineView 控件:

WebEngineView {
    id: authorizationWebView
    anchors.fill: parent
    visible: false
}

这个简化示例展示了 C++ 类中所需的 API

class HttpExample : public QObject
{
    Q_OBJECT
#ifdef QT_QML_LIB
    QML_NAMED_ELEMENT(OAuth2)
#endif
public:
    Q_INVOKABLE void authorize();

signals:
    void authorizationCompleted(bool success);
    void authorizeWithBrowser(const QUrl &url);

随后在 QML 端调用这些 API 来调用 `WebEngineView ` 以处理授权:

onAuthorizeWithBrowser:
    (url) => {
        console.log("Starting authorization with WebView")
        authorizationWebView.url = url
        authorizationWebView.visible = true
    }
onAuthorizationCompleted:
    (success) => {
        console.log("Authorized: " + success);
        authorizationWebView.visible = false
    }

重定向 URI 方案

重定向 URI 方案的选择(http 、https 或custom-uri 方案)会影响 Qt WebEngine。

HTTP 回环 URI

使用http 作为回环重定向 URI 以及QOAuthHttpServerReplyHandler 时,处理方式与系统浏览器类似。Qt WebEngine 会将授权请求重定向至回复处理程序的 localhost 服务器,这与系统浏览器的处理方式相同。

自定义方案 URI

对于自定义方案 URI(例如com.example.myqtapp:/redirect )和QOAuthUriSchemeReplyHandler ,其处理流程也与系统浏览器类似。

主要区别在于,应用程序无需像iOS/macOS 上的通用链接(Universal Links)或Android 上的应用链接(App Links)那样进行配置,具体请参阅QOAuthUriSchemeReplyHandler 文档。

m_handler.setRedirectUrl(QUrl{"com.example.myqtapp://oauth2redirect"_L1});
m_oauth.setReplyHandler(&m_handler);

connect(&m_oauth, &QAbstractOAuth::authorizeWithBrowser, this, [this](const QUrl &url) {
    mainWindow.show();
    webView->load(url);
    webView->show();
});
connect(&m_oauth, &QAbstractOAuth::granted, this, [this]() {
    // Here we use QNetworkRequestFactory to store the access token
    m_api.setBearerToken(m_oauth.token().toLatin1());
    m_handler.close();
    webView->close();
});

从技术上讲,其工作原理是: Qt WebEngine 当遇到未处理的 URI 方案时,会调用QDesktopServices::openUrl() 方法,而其对应的QOAuthUriSchemeReplyHandler 则负责监听这些 URI 方案。

HTTPS URI

对于https URI 和QOAuthUriSchemeReplyHandler ,其工作逻辑略有不同。与自定义方案 URI类似,应用程序无需进行配置,但我们需要在授权阶段结束时向 Web 引擎提供重定向。

connect(webView, &QWebEngineView::urlChanged, this, [this](const QUrl &url){
    m_handler.handleAuthorizationRedirect(url);
});

之所以需要这样做,是因为从 Qt WebEngine 从技术角度来看,重定向 URL 是一个有效的https URL,系统默认会尝试跳转至该地址。

为防止此类导航尝试以及授权码意外泄露(请考虑重定向 URL 的域名不在您控制范围内的情况),应采用更严格的过滤机制。此外,强烈建议使用QOAuth2AuthorizationCodeFlow::PkceMethod ,因为这可以减轻授权码劫持的影响。

例如:

connect(webView->page(), &QWebEnginePage::navigationRequested,
        this, [this](QWebEngineNavigationRequest &request) {
    if (request.navigationType() == QWebEngineNavigationRequest::RedirectNavigation
        && m_handler.handleAuthorizationRedirect(request.url())) {
        request.reject();
        webView->close();
    } else {
        request.accept();
    }
});

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.