Qt5-QML: automatic authentication username and password with on a third party device

喜夏-厌秋 提交于 2020-01-25 04:14:26

问题


After understanding how to integrate JavaScript functions into Qt-QML I am now trying to apply what I have learned in my previous post to a small real world example in my lab.

I am trying to access to my robots via wi-fi using using a third party device present in my lab.

I have a log-in form provided by the device as shown in the print screen given below. The address is, for example, https://123.456.789.123:7878 (which I made up but it is for understanding the idea):

After navigating the html page using the inspector tool I arrived to the log in button class as shown below:

The problem I have is that I am now trying to autofill the password of the log-in and automatically access it. After logging in I should be able to see the page below, but I don't.

I should mention that I reused the Quick Nanao Browser Example beacause it does work well when there is need to by-pass a windows that requires certification.

The example

I worked a lot on the Quick Nanao Browser Example to make it much more short and focusing exactly where the problem is and how I am trying to solve it.

The code snippet I am using is the one below:

main.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();
    }
}

Thank you very much for providing some guidance on how to solve this problem and how to move on.


回答1:


For a next occasion it is necessary to show what you have tried since saying that it does not work and using my previous code is not enough, each login depends on each system so there is no generic solution.

From the little HTML you have shown you can deduce that:

  • The username input has an id of "username".
  • The password input has an id of "password".
  • when the button is pressed, the function "LSubmit()" that makes the verification is called.

From my experiment with my router there is always a delay in the creation of the DOM, in addition to the url that entered a "/" is added at the end if it does not exist

Considering the above, the solution is:

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"
    }
}


来源:https://stackoverflow.com/questions/58921220/qt5-qml-automatic-authentication-username-and-password-with-on-a-third-party-de

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!