Qt5-QML:在第三方设备上自动验证用户名和密码

Posted

技术标签:

【中文标题】Qt5-QML:在第三方设备上自动验证用户名和密码【英文标题】:Qt5-QML: automatic authentication username and password with on a third party device 【发布时间】:2019-11-18 19:01:51 【问题描述】:

在了解了如何将 javascript 函数集成到 Qt-QML 中之后,我现在正在尝试将我在 my previous post 中学到的知识应用到我实验室中的一个小型实际示例中。

我正在尝试使用实验室中的第三方设备通过 wi-fi 访问我的机器人。

我有一个由设备提供的登录表格,如下面的打印屏幕所示。例如,地址是https://123.456.789.123:7878(这是我编的,但这是为了理解这个想法):

使用inspector tool 导航html 页面后,我到达了log in 按钮类,如下所示:

问题我现在正在尝试自动填充log-in 的密码并自动访问它。登录后我应该可以看到下面的页面,但我没有。

我应该提到我重用了Quick Nanao Browser Example,因为它在需要绕过需要认证的窗口时工作得很好。

示例

我在 Quick Nanao 浏览器示例上做了很多工作,以使其更简短,并准确地关注问题所在以及我试图解决它的方法。

我使用的代码 sn-p 如下:

ma​​in.cpp

#include <QtQml/QQmlApplicationEngine>
#include <QtQml/QQmlContext>
#include <QtWebEngine/qtwebengineglobal.h>
static QUrl startupUrl()

    QUrl ret;
    QStringList args(qApp->arguments());
    args.takeFirst();
    for (const QString &arg : qAsConst(args)) 
        if (arg.startsWith(QLatin1Char('-')))
             continue;
        ret = Utils::fromUserInput(arg);
        if (ret.isValid())
            return ret;
    
    return QUrl(QStringLiteral("https://123.456.789.123:7878"));


int main(int argc, char **argv)

    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QtWebEngine::initialize();
    Application app(argc, argv);
    QQmlApplicationEngine appEngine;
    Utils utils;
    appEngine.rootContext()->setContextProperty("utils", &utils);
    appEngine.load(QUrl("qrc:/ApplicationRoot.qml"));
    if (!appEngine.rootObjects().isEmpty())
        QMetaObject::invokeMethod(appEngine.rootObjects().first(), "load", Q_ARG(QVariant, startupUrl()));
    else
        qFatal("Failed to load sources");
    return app.exec();

ApplicationRoot.qml

import QtQuick 2.1
import QtWebEngine 1.9
QtObject 
    id: root
    property string script_password: "
        setTimeout(function()
            var input_password = document.getElementsByName('password')[0];
            input_password.value = '%1';
            var button = document.getElementById('passwordNext');
            button.click();
            , 100);
            ".arg(password)

    property QtObject defaultProfile: WebEngineProfile 
    property QtObject otrProfile: WebEngineProfile 
        offTheRecord: true
    
    property Component browserWindowComponent: BrowserWindow 
        applicationRoot: root
        onClosing: destroy()
        
    function createWindow(profile) ...
    function createDialog(profile) ...
    function load(url) ...

BrowserWindow.qml

import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.0
import QtQuick.Window 2.1
import QtWebEngine 1.9

ApplicationWindow 
    id: browserWindow

    property string password: "abcdefghilmno"

    property QtObject applicationRoot
    property Item currentWebView: tabs.currentIndex < tabs.count ? tabs.getTab(tabs.currentIndex).item : null
    property int previousVisibility: Window.Windowed
    width: 1300
    height: 900
    visible: true
    title: currentWebView && currentWebView.title
    Component.onCompleted: flags = flags | Qt.WindowFullscreenButtonHint
    toolBar: ToolBar ...
    // Necessary to accept server's certificate
    TabView ...
    // Showing Manager Window
    WebEngineView 
        id: devToolsView
        anchors.left: parent.left
        anchors.right: parent.right
        anchors.bottom: parent.bottom
        onNewViewRequested: function(request) 
            var tab = tabs.createEmptyTab(currentWebView.profile);
            tabs.currentIndex = tabs.count - 1;
            request.openIn(tab.item);
        
    
    // By-Passing the Server's Certificate using sslDialog
    MessageDialog ...
    DownloadView 
        id: downloadView
        visible: false
        anchors.fill: parent
    
    function onDownloadRequested(download) 
        downloadView.visible = true;
        downloadView.append(download);
        download.accept();
    

非常感谢您就如何解决此问题以及如何继续提供一些指导。

【问题讨论】:

【参考方案1】:

下次有必要展示你的尝试,因为说它不起作用并且使用我以前的代码是不够的,每次登录都取决于每个系统,所以没有通用的解决方案。

从您展示的小 HTML 中,您可以推断:

用户名输入的 ID 为“用户名”。 密码输入的 id 为“password”。 按下按钮时,会调用进行验证的函数“LSubmit()”。

从我对路由器的实验来看,创建 DOM 总是有延迟,除了输入“/”的 url 如果不存在则添加到末尾

综合以上,解决办法是:

import QtQuick 2.13
import QtQuick.Controls 2.13
import QtWebEngine 1.9

ApplicationWindow
    id: root
    width: 640
    height: 480
    visible: true

    property string username: "USERNAME"
    property string password: "PASSWORD"

    QtObject
        id: internals
        property string login_script: "
            console.log('start');
            var input_username = document.getElementById('username');
            console.log('username');
            console.log(input_username);
            input_username.value = '%1';
            var input_password = document.getElementById('password');
            console.log('password');
            console.log(input_password);
            input_password.value = '%2';
            console.log('clicked');
            LSubmit();
            console.log('end');
        ".arg(username).arg(password);
    

    Timer 
        id: timer
        interval: 1000; repeat: false
        onTriggered: view.runJavaScript(internals.login_script)
    

    WebEngineView 
        id: view
        anchors.fill: parent
        onUrlChanged: 
            console.log(url)
            if(url == Qt.resolvedUrl("https://123.456.789.123:7878/"))
                timer.running = true   
            
        
        onCertificateError: function(error) 
            error.ignoreCertificateError();
        
        Component.onCompleted: view.url = "https://123.456.789.123:7878"
    

【讨论】:

感谢 eyllanesc 花时间阅读问题。问题是,因为我必须访问需要证书的页面,所以“无法访问站点”正在阻止加载页面。如图here。我之所以使用Quick Nano Browser Example是因为有可能使用ignoreCertificateError()表示的here。 @Emanuele 我建议你不要盲目地使用代码,了解正在做什么,试验和使用代码。例如,“Quick Nano Browser”代码对此很感兴趣,您应该问自己:当调用调用了 ignoreCertificateError() 槽的 MessageDialog 时?我的印象是您想使用大量代码而不试图理解它。嗯 它几乎可以工作,我看到了登录页面,但密码的行编辑没有自动填写密码,我试图了解原因。 @Emanuele 尝试在 chrome 控制台选项卡中运行 js 并检查它是否引发错误。很遗憾,由于显而易见的原因,我无法再为您提供帮助。 @Emanuele 使用我的脚本,您必须打印 url,您会得到什么?

以上是关于Qt5-QML:在第三方设备上自动验证用户名和密码的主要内容,如果未能解决你的问题,请参考以下文章

Qt5-QML:ColumnLayout 在嵌套循环中覆盖另一个 ColumnLayout

如何使用GoogleAuthenticator

验证码错误无法读取cookie 不管我有没有输密码和验证码都出现这提示

仅使用密码而不是 TouchID 的设备上的本地身份验证

如何使用GoogleAuthenticator

如何使用 Python 和/或 Javascript 自动验证 ngrok 密码?