12

通过 Chrome Console 填写表单内容未生效

 4 years ago
source link: https://demokn.com/posts/troubleshooting-fill-a-react-form-from-chrome-console/index.html?
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

通过 Chrome Console 填写表单内容未生效

Published on Nov 15, 2019

出于某些原因,需要通过浏览器插件的方式实现自动登录某平台。 这里选择 Google Chrome 浏览器。

方案设想很简单,无非就是通过 JS 找到表单元素,自动填入用户名、密码,再触发一下登录按钮的 click 事件。完事。

在开始写插件之前,总要先通过 Chrome Console 验证一下方案的可行性吧。代码也是相当简单。

$("#username").value = "USERNAME"
$("#password").value = "PASSWORD"
$("#submit").click()

然而,“卧槽,无情” 的一幕出现了,页面上竟然提示我 “请输入账号”。 可明明已经给你赋值了呀,输入框里不还填充着明明赋值的内容呢,难道你是盲僧吗?

页面提示请输入账号

没办法,只能开启我的漫漫 debug 之路了。

  • 手动输入用户名密码,手动点击登录; 成功
  • 手动输入用户名密码,脚本触发登录; 成功
  • 脚本输入用户名密码,手动点击登录; 失败
  • 使用其他网站(我用的 GitHub)尝试,脚本输入用户名密码,脚本触发登录; 成功了,成功了,成功了
  • 脚本输入用户名密码,并分别点击用户名密码输入框,使其获取焦点,手动点击登录; 失败
  • 脚本输入用户名密码,并分别点击用户名密码输入框,并再追加输入内容,手动点击登录; 成功
  • 脚本输入用户名密码,并分别点击用户名密码输入框,并再追加输入内容,脚本点击登录; 成功

哦,对了,还有一种成功的情况是使用浏览器的密码自动填充功能,也是可以正常登录的。

根据以上测试情况,初步猜想应该是使用脚本直接赋值的时候,输入框DOM元素上的某个事件没触发。

接着,用 Chrome 开发者工具的 search 功能,查找报错内容 “请输入账号”,找到了定义在某个js文件里的代码:

_this.validation = {
  login: [{ f: _validator.isEmpty, msg: '请输入账号' }],
  password: [{ f: _validator.isEmpty, msg: '请输入密码' }],
};

继续猜测,报错“请输入账号”是因为验证器为空,验证器为空的原因应该是验证方法没有执行, 而验证方法没被执行的原因还是因为没有监听到某个指定的事件。 至于到底是什么事件,我也不知道,也没从代码里找到什么有用的线索。 不过倒是从代码里看出这是用 react 框架写的,在后面google的时候也算是一个用得到的关键词吧。

接下来就是通过 Chrome Console 脚本触发事件,逐一验证了。 根据上面的测试结果 脚本输入用户名密码,并分别点击用户名密码输入框,并再追加输入内容,手动点击登录; 成功 。 我选择了几个可能性比较大的事件: onchange, oninput, onkeydown, onkeyup, onkeypress 。 测试代码如下:

var change = document.createEvent("HTMLEvents")
change.initEvent("change")

var input = document.createEvent("HTMLEvents")
input.initEvent("input")

var focus = document.createEvent("HTMLEvents")
focus.initEvent("focus")

var blur = document.createEvent("HTMLEvents")
blur.initEvent("blur")

var keydown = document.createEvent("KeyboardEvent")
keydown.initKeyboardEvent("keydown")

var keyup = document.createEvent("KeyboardEvent")
keyup.initKeyboardEvent("keyup")

var keypress = document.createEvent("KeyboardEvent")
keypress.initKeyboardEvent("keypress")

var el = $("#username")
el.value = "USERNAME"
el.dispatchEvent(change)
el.dispatchevent(input)
el.dispatchEvent(keydown)
el.dispatchEvent(keyup)
el.dispatchEvent(keypress)

然而,又是“卧槽,无情”的一幕,还是不行。

继续尝试,google,尝试,此处省略半小时。。。

最终发现,确实是 input 事件的问题,至于上面的事件测试中明明有 input 事件却没生效的原因是: 初始化事件时,没有明确指定事件的冒泡属性为 true , 即 input.initEvent("input", {bubbles: true}) 至于,这之中涉及到的 DOM事件, 事件监听, 事件触发, 事件冒泡 和 React组件State 等,我也不是专业前端,很难讲明白,有兴趣的就自行 google 吧。

完整的代码如下:

var inputEvent = document.createEvent("HTMLEvents")
inputEvent.initEvent("input", {bubbles: true})

$("#username").value = "USERNAME"
$("#username").dispatchEvent(inputEvent)
$("#password").value = "PASSWORD"
$("#password").dispatchEvent(inputEvent)
$("#submit").click()

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK