Qt OAuth2 브라우저 지원
OAuth2 사용자 에이전트
OAuth2 인증 단계는 사용자 에이전트에 의존하며, 일반적으로 시스템 브라우저 또는 임베디드 사용자 에이전트( Qt WebEngine.
시스템 브라우저와 임베디드 사용자 에이전트 중 어떤 것을 선택할지는 여러 가지 요인에 따라 달라집니다. 다음은 몇 가지 주요 고려 사항에 대해 설명합니다:
- 시스템 브라우저에 이미 사용자의 로그인이 활성화되어 있을 수 있습니다. 따라서 기존 로그인을 사용할 수 있으므로 인증 단계에서 사용자 인증이 더 간단할 수 있습니다. 임베디드 사용자 에이전트 사용자는 일반적으로 새 로그인을 수행해야 하는 것과는 대조적입니다. 반면에 시스템 브라우저에 로그인 세션을 남겨두는 것이 항상 바람직한 것은 아닐 수 있습니다. 시스템 브라우저는 애플리케이션 사용 데이터를 다른 당사자와 공유할 수도 있습니다.
- 시스템 브라우저는 일반적으로 사용자에게 친숙하며 로그인 시 익숙한 사용자 환경을 제공합니다. 반면 임베디드 사용자 에이전트는 덜 익숙한 모양과 느낌을 제공할 수 있지만 애플리케이션 개발자는 로그인 상호 작용을 별도의 브라우저 창에서 수행하지 않고 애플리케이션 창의 일부로 임베드할 수 있습니다. 또한 애플리케이션 개발자는 더 이상 필요하지 않은 경우 임베드된 사용자 에이전트를 자동으로 닫을 수 있습니다.
- 시스템 브라우저는 주소 표시줄과 인증서 유효성 검사 등 사용자에게 익숙한 보안 시각적 요소를 제공합니다. 임베디드 사용자 에이전트에서는 이러한 시각적 요소가 표시되지 않을 수 있습니다. 또한 시스템 브라우저는 기본 운영 체제의 보안 기능을 더 잘 활용할 수 있습니다.
- 임베디드 사용자 에이전트는 사용자가 입력하는 모든 보안 자격 증명에 액세스할 수 있습니다.
- 모든 플랫폼이
https
또는 사용자 정의 uri-scheme 리디렉션 URL 처리를 지원하는 것은 아닙니다( QOAuthUriSchemeReplyHandler 참조 ). 이러한 플랫폼에서는 임베드된 사용자 에이전트를 사용하여 제한을 해결할 수 있습니다. - 애플리케이션의 일부로 임베디드 사용자 에이전트를 포함하면 일반적으로 구성 요소가 커지므로 애플리케이션의 저장 공간이 증가합니다. 반면에 모든 사용 사례에서 시스템 브라우저를 사용할 수 없거나 애플리케이션이 이미 다른 용도로 임베디드 사용자 에이전트를 사용하고 있을 수도 있습니다.
이러한 점을 고려할 때 네이티브 애플리케이션에는 시스템 브라우저를 사용하는 것이 좋습니다. 하지만 위의 몇 가지 사항에서 알 수 있듯이 임베디드 사용자 에이전트를 사용해야 하는 유효한 사용 사례가 여전히 있을 수 있습니다.
시스템 브라우저 사용
시스템 브라우저를 사용하려면 시스템 브라우저를 열고 애플리케이션에서 구성한 인증 URL로 이동해야 합니다. 일반적인 사용법은 다음과 같습니다:
connect(&m_oauth, &QAbstractOAuth::authorizeWithBrowser, this, &QDesktopServices::openUrl);
이 코드는 QAbstractOAuth::authorizeWithBrowser 신호와 QDesktopServices::openUrl 슬롯을 연결합니다. 그러면 시스템 브라우저가 열리고 사용자는 필요한 인증 및 권한 부여를 수행합니다. 애플리케이션이나 Qt 라이브러리는 시스템 브라우저를 직접 제어할 수 없으며, 일반적으로 인증이 완료된 후에도 브라우저는 열려 있는 상태로 유지됩니다.
자세한 내용과 시스템 브라우저에서 지원되는 리디렉션 URL 체계에 대해서는 Qt OAuth2 개요, QOAuthHttpServerReplyHandler, 및 QOAuthUriSchemeReplyHandler 을 참조하십시오.
사용 Qt WebEngine
Qt WebEngine 는 웹 브라우저 엔진을 제공하여 웹 콘텐츠를 Qt 애플리케이션에 직접 임베드할 수 있습니다.
핵심 제어 기능과 함께 QtWidgets 및 QtQuick 애플리케이션을 위한 사용하기 쉬운 뷰가 함께 제공됩니다. 이러한 뷰는 OAuth2 인증에서 사용자 에이전트로 사용할 수 있습니다. Qt WebEngine 는 크고 다재다능한 모듈이며, 이 문서에서는 OAuth2 인증과 함께 사용하는 데 중점을 둡니다.
Qt XML을 애플리케이션의 일부로 임베드하는 방법에는 여러 가지가 있습니다( WebEngine ). 실용적인 관점에서 주요 고려 사항은 다음과 같습니다:
- QtQuick과 QtWidgets 애플리케이션. 이는 QtNetworkAuth 클래스와 필요한 통합을 설정하는 방법에 영향을 줍니다.
- 리디렉션 URI 체계. 이는 사용할 QtNetworkAuth 응답 핸들러 클래스와 그 방법에 영향을 줍니다 ( Qt OAuth2 개요 참조).
QtQuick과 QtWidgets 응용 프로그램
Qt WebEngine 는 OAuth2 인증을 위해 QtQuick과 QtWidgets 응용 프로그램 모두에 사용할 수 있습니다. 주요 차이점은 몇 가지 필요한 인에이블러를 설정하는 방법에 있습니다.
다음은 간단한 QWebEngineView (QtWidget) 설정의 예시입니다. 오류 처리 및 잠재적인 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 애플리케이션의 경우 흐름은 원칙적으로 동일하지만 QWebEngineView 위젯 대신 WebEngineView QML 요소를 사용합니다:
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 측에서 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 은 시스템 브라우저와 유사하게 응답 처리기의 로컬 호스트 서버로 권한을 리디렉션합니다.
사용자 정의 스키마 URI
사용자 정의 스키마 URI(예: com.example.myqtapp:/redirect
) 및 QOAuthUriSchemeReplyHandler 의 경우에도 시스템 브라우저와 유사하게 흐름이 작동합니다.
가장 큰 차이점은 QOAuthUriSchemeReplyHandler 문서에 설명된 대로 iOS/macOS의 유니버설 링크 또는 Android의 앱 링크와 유사하게 애플리케이션을 구성할 필요가 없다는 것입니다.
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 은 수신 대기합니다.
https URI
https
URI와 QOAuthUriSchemeReplyHandler 에서는 로직이 약간 변경됩니다. 사용자 정의 스키마 URI와 마찬가지로 애플리케이션을 구성할 필요는 없지만 인증 단계가 끝날 때 웹 엔진에 리디렉션을 제공해야 합니다.
connect(webView, &QWebEngineView::urlChanged, this, [this](const QUrl &url){ m_handler.handleAuthorizationRedirect(url); });
이 작업을 수행해야 하는 이유는 Qt WebEngine 관점에서 리디렉션 URL은 유효한 https
URL이며 기본적으로 이 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(); } });
© 2025 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.