Qt5-QML:在第三方设备上自动认证用户名和密码
Qt5-QML: automatic authentication username and password with on a third party device
了解如何将 JavaScript
函数集成到 Qt-QML
之后,我现在正尝试将我在 中学到的知识应用到我实验室中的一个真实世界的小例子中。
我正在尝试使用实验室中的第三方设备通过 Wi-Fi 访问我的机器人。
我有一个设备提供的登录表单,如下面的打印屏幕所示。地址是,例如,https://123.456.789.123:7878
(这是我编的,但这是为了理解这个想法):
使用 inspector tool
浏览 html
页面后,我到达了 log in
按钮 class,如下所示:
我遇到的问题是我现在试图自动填充 log-in
的密码并自动访问它。登录后我应该可以看到下面的页面,但是我没有。
我应该提到我重用了 Quick Nanao Browser Example,因为它在需要绕过需要认证的 windows 时效果很好。
例子
我在 Quick Nanao Browser Example 上做了很多工作,以使其更简短,并准确地关注问题所在以及我如何尝试解决它。
我使用的代码片段如下:
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();
}
}
非常感谢您就如何解决此问题以及如何继续提供一些指导。
下一次有必要展示你尝试过的东西,因为说它不起作用并且使用我以前的代码是不够的,每次登录都取决于每个系统,所以没有通用的解决方案。
从您展示的 HTML 中可以推断出:
- 用户名输入的 ID 为 "username"。
- 密码输入的 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"
}
}
了解如何将 JavaScript
函数集成到 Qt-QML
之后,我现在正尝试将我在
我正在尝试使用实验室中的第三方设备通过 Wi-Fi 访问我的机器人。
我有一个设备提供的登录表单,如下面的打印屏幕所示。地址是,例如,https://123.456.789.123:7878
(这是我编的,但这是为了理解这个想法):
使用 inspector tool
浏览 html
页面后,我到达了 log in
按钮 class,如下所示:
我遇到的问题是我现在试图自动填充 log-in
的密码并自动访问它。登录后我应该可以看到下面的页面,但是我没有。
我应该提到我重用了 Quick Nanao Browser Example,因为它在需要绕过需要认证的 windows 时效果很好。
例子
我在 Quick Nanao Browser Example 上做了很多工作,以使其更简短,并准确地关注问题所在以及我如何尝试解决它。
我使用的代码片段如下:
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();
}
}
非常感谢您就如何解决此问题以及如何继续提供一些指导。
下一次有必要展示你尝试过的东西,因为说它不起作用并且使用我以前的代码是不够的,每次登录都取决于每个系统,所以没有通用的解决方案。
从您展示的 HTML 中可以推断出:
- 用户名输入的 ID 为 "username"。
- 密码输入的 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"
}
}