0
jsDom使用以及简易滑动验证码跳过
黄粱一梦2024-03-0816
jsDom介绍
sdom 是一个纯粹由 JavaScript 实现的一系列 Web 标准,特别是 WHATWG 组织制定的 DOM 和 HTML 标准,用于在 Node.js 中使用。大体上来说,该项目的目标是模拟足够的 Web 浏览器子集,以便用于测试和挖掘真实世界的 Web 应用程序。
安装使用jsDom
npm i jsdom
目录结构
app.js
const express = require('express')
const app = express()
const router = require('./router/index')
const path = require('path')
app.use(router)
app.use('/public',express.static(path.join(__dirname,'./template')))
app.listen(20315,() => {
console.log('app run on server http://localhost:20315')
})
router/index.js
const express = require('express')
const moment = require('moment')
const jsdom = require('jsdom')
const { JSDOM } = jsdom;
const axios = require('axios')
const router = express.Router()
const uuid = require('uuid')
function allFn(req,res,next){
res.set('Access-Control-Allow-Origin','*')
console.log("Method::",req.method+"---","Path::",req.path+"---","createTime::",moment().format('YYYY-MM-DD HH:mm:ss'))
next()
}
router.use(allFn)
router.get('/test',(req, res) => {
let responseStr = '本次请求id:::'+uuid.v1()
console.log(responseStr)
res.send(responseStr)
})
const storage = {
data: {},
getItem(key) {
return this.data[key];
},
setItem(key, value) {
this.data[key] = value;
},
removeItem(key) {
delete this.data[key];
},
clear() {
this.data = {};
}
};
getHtml('http://localhost:20315/public/index.html').then(val => {
let template = val
let jsDomInstance = new JSDOM(template,{
runScripts: "dangerously",
resources: "usable",
})
let {window} = jsDomInstance
window.localStorage = storage;
let stemp = window.document.createElement('script')
stemp.text = `
window.onload = function(){
const done = false // 是否开启定时脚本
console.log('自定义脚本插入成功·····')
if(done) {
setInterval(() => {
console.log('插入脚本定时请求---200毫秒一次')
let btn = document.querySelector('button')
btn.click()
},2000)
}else {
let btn = document.querySelector('button')
btn.click()
}
}
`
window.document.body.appendChild(stemp)
/* 插入axios脚本 */
let axiosScript = window.document.createElement('script')
axiosScript.src = 'https://unpkg.com/axios/dist/axios.min.js'
window.document.body.appendChild(axiosScript)
/* 插入js拖动校验脚本 */
let moveScript = window.document.createElement('script')
moveScript.text = `
/*创建event*/
let eve = sideInner.dispatchEvent(new MouseEvent('mousedown'),{
bubbles: false, // 默认值false, 事件是否冒泡
cancelable: false, // 默认值false, 事件能否被取消
composed: false // 默认值false, 事件是否会在影子DOM根节点之外触发侦听器。
})
// sideInner.dispatchEvent(new MouseEvent('mousemove'),{
// clientX:320,
// clientY:181
// })
// 创建鼠标移动事件
let executionCount = 452 //执行次数
console.log('开始分发事件')
for(let i=100;i<=executionCount;i++) {
setTimeout(()=> {
sideInner.dispatchEvent(new MouseEvent('mousemove',{
bubbles: true,
cancelable: true,
view: window,
clientX: i,
clientY: 181,
}))
if(i == executionCount) {
window.dispatchEvent(new MouseEvent('mouseup'),{})
console.log('解除自动分发事件')
}
},i*3)
}
`
window.document.body.appendChild(moveScript)
})
let targetPath = 'https://whriten.gitee.io'
function getHtml(targetPath){
return new Promise((resolve, reject) => {
axios.get(targetPath).then(response => {
resolve(response.data)
}).catch(err => {
reject(err)
})
})
}
getHtml(targetPath).then(res => {
let jsDomInstance = new JSDOM(res,{
runScripts: "dangerously",
resources: "usable"
})
let {window} = jsDomInstance.window
let script = window.document.createElement('script')
let host = 'https://whriten.gitee.io'
let axiosScript = window.document.createElement('script')
axiosScript.src = 'https://unpkg.com/axios/dist/axios.min.js'
window.document.body.appendChild(axiosScript)
let pathUrl = ''
script.text = `
window.onload = function(){
let host = 'https://whriten.gitee.io'
console.log('插入脚本被加载····')
}
`
pathUrl = 'https://whriten.gitee.io/blogs/other/guide.html'
// axios(pathUrl).then(val => {
// console.log('val',val.data)
// })
window.document.body.appendChild(script)
})
module.exports = router
插入执行js脚本
jsdom最强大的能力就是可以执行jsdom内部的脚本。这些脚本可以修改页面内容并访问 jsdom 实现的所有 Web 平台 API。
::: danger
jsDom默认关闭引入脚本的执行,需要我们在配置项中开启 runScripts: "dangerously",
,resources: "usable",
:::
示例>
目标效果
当拖动到最右边时候完成验证发起请求
验证成功之后发送请求
接收请求
代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
*{padding:0px;margin:0px;}
.box-out {
margin-left: 100px;
margin-top: 100px;
position: relative;
width: 400px;
height: 30px;
background: #ececec;
}
.box-inner {
position: absolute;
z-index: 2;
left: 0px;
top: 50%;
transform: translateY(-50%);
width: 50px;
height: 30px;
background-color: #fff;
box-shadow: 0px 0px 10px #ccc;
cursor: pointer;
}
.in {
position: absolute;
left: 0px;
top: 50%;
transform: translateY(-50%);
background-color: greenyellow;
width: 30px;
height: 100%;
}
.box-inner::after {
position: absolute;
content: "";
top: 50%;
transform: translate(-50%,-50%);
left: 50%;
width: 80%;
height: 60%;
background-color: greenyellow;
}
</style>
</head>
<body>
<h2>测试文本</h2>
<button>获取远程数据</button>
<!-- <script src="https://unpkg.com/axios/dist/axios.min.js"></script>-->
<script src="./util/axios.min.js"></script>
<div class="box-out">
<div class="box-inner"></div>
<div class="in"></div>
</div>
<script>
let btn = document.querySelector('button')
btn.addEventListener('click', function(){
console.log('按钮点击成功!!!发送信息')
axios('http://localhost:20315/test').then(response => {
console.log(response.data)
})
})
</script>
<button class="dispatch">dispatchEvent</button>
<!-- 滑动验证 -->
<script>
let dispatch = document.querySelector('.dispatch')
let minSize = 5 // 误差多少px
let sideOut = document.querySelector('.box-out')
let sideInner = document.querySelector('.box-inner')
let inDom = document.querySelector('.in')
var afterStyle = window.getComputedStyle(sideOut, "::after");
sideInner.addEventListener('mousedown',(e) => {
// console.log('触发鼠标点击事件',e)
sideOut.addEventListener('mousemove',moveHandler)
})
function moveHandler(e){
// console.log('鼠标移动事件',e)
let abouX = (sideInner.style.width / 2)// 本身一半
let targetX = e.x - 100 - abouX
let outWidth = sideOut.style.width
let innerWidth = sideInner.style.width
// 可用拖动距离
let canMoveX = 350
let leftx = sideInner.style.left
if (targetX > canMoveX) {
inDom.innerText = '验证成功'
console.log('滑块验证成功!!!!!!!!!!!!!!!')
btn.click()
return
}
sideInner.style.left = (targetX) + 'px'
inDom.style.width = targetX + 'px'
inDom.innerText = ''
}
window.addEventListener('mouseup',() => {
sideOut.removeEventListener('mousemove',moveHandler)
})
</script>
</body>
</html>
jsDom自动化实现
const express = require('express')
const moment = require('moment')
const jsdom = require('jsdom')
const { JSDOM } = jsdom;
const axios = require('axios')
const router = express.Router()
const uuid = require('uuid')
function getHtml(targetPath){
return new Promise((resolve, reject) => {
axios.get(targetPath).then(response => {
resolve(response.data)
}).catch(err => {
reject(err)
})
})
}
getHtml('http://localhost:20315/public/index.html').then(val => {
let template = val
let jsDomInstance = new JSDOM(template,{
runScripts: "dangerously",
resources: "usable",
})
let {window} = jsDomInstance
window.localStorage = storage;
/* 插入axios脚本 */
let axiosScript = window.document.createElement('script')
axiosScript.src = 'https://unpkg.com/axios/dist/axios.min.js'
window.document.body.appendChild(axiosScript)
/* 插入js拖动校验脚本 */
let moveScript = window.document.createElement('script')
moveScript.text = `
/*创建event*/
let eve = sideInner.dispatchEvent(new MouseEvent('mousedown'),{
bubbles: false, // 默认值false, 事件是否冒泡
cancelable: false, // 默认值false, 事件能否被取消
composed: false // 默认值false, 事件是否会在影子DOM根节点之外触发侦听器。
})
// 创建鼠标移动事件
let executionCount = 452 //执行次数
console.log('开始分发事件')
for(let i=100;i<=executionCount;i++) {
setTimeout(()=> {
sideInner.dispatchEvent(new MouseEvent('mousemove',{
bubbles: true,
cancelable: true,
view: window,
clientX: i,
clientY: 181,
}))
if(i == executionCount) {
window.dispatchEvent(new MouseEvent('mouseup'),{})
console.log('解除自动分发事件')
}
},i*3)
}
`
window.document.body.appendChild(moveScript)
})
执行效果
可以看到已经通过验证并发起了请求
版权声明
本文系作者 @黄粱一梦 转载请注明出处,文中若有转载的以及参考文章地址也需注明。\(^o^)/~
Preview