问题
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