参考资料:https://github.com/sxei/chrome-plugin-demo?tab=readme-ov-file
代码目录
|-manifest.json
|-content-script.js
|-recognition_styles.css
|-popup.html
|-popup.js
|-icon.png主要代码实现
manifest.json
{
"manifest_version": 3,
"name": "图片验证码识别插件",
"version": "1.0",
"description": "用于识别tap项目登录页的canvas字符验证码",
"author": "carolin-violet",
"icons": {
"48": "icon.png",
"128": "icon.png"
},
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content-script.js"],
"css": ["recognition_styles.css"],
"run_at": "document_start"
}
],
"permissions": ["webRequest", "webRequestBlocking", "storage", "scripting"],
"homepage_url": "https://github.com/carolin-violet"
}
content-script.js
const userInfoObj = {
account: "violet",
password: "Trendy@123",
code: "",
};
// 获取canvas图片内容
function getImg() {
const canvasContainer = document.querySelector(".identityCode");
const canvas = canvasContainer.querySelector("canvas");
return new Promise((resolve, reject) => {
canvas.toBlob(
(blob) => {
if (blob) {
resolve(blob);
} else {
reject(new Error("Failed to create Blob"));
}
},
"image/png",
1
);
});
}
// api调用
function getCaptchaCode(formData) {
const url = "http://127.0.0.1:5000/img_recognition"; // 替换为你的 API 地址
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open("POST", url);
xhr.onload = function () {
if (xhr.status >= 200 && xhr.status < 300) {
// 处理接收到的数据
console.log("数据:", xhr.responseText);
resolve(xhr.responseText);
} else {
console.error("请求失败:", xhr.status);
reject(xhr.status);
}
};
xhr.onerror = function () {
console.error("请求错误");
document.getElementById("response").textContent = "请求错误";
};
xhr.send(formData);
});
}
function recognition() {
getImg().then((imgBlob) => {
const file = new File([imgBlob], "image.png", { type: imgBlob.type });
const formData = new FormData();
formData.append("file", file);
getCaptchaCode(formData).then((code) => {
userInfoObj.code = code;
// 自动填入用户信息
writeUserInfo();
});
});
}
// 监听html文档加载完成
document.addEventListener("DOMContentLoaded", function () {
const violet_recognition_button = document.createElement("div");
violet_recognition_button.innerText = "填充";
violet_recognition_button.className = "violet_recognition_button";
document.body.appendChild(violet_recognition_button);
violet_recognition_button.onclick = recognition;
});
// 自动向input输入框中写入用户名密码验证码
function writeUserInfo() {
const inputList = document.querySelectorAll(".el-input__inner");
const accountInput = inputList[0];
const passwordInput = inputList[1];
const captchaInput = inputList[2];
simulateInput(accountInput, userInfoObj.account);
simulateInput(passwordInput, userInfoObj.password);
simulateInput(captchaInput, userInfoObj.code);
}
// 模拟输入
function simulateInput(element, value) {
const inputEvent = new Event("input", { bubbles: true });
element.value = value;
element.dispatchEvent(inputEvent);
}
recognition_styles.css
/*
点击按钮
*/
.violet_recognition_button {
position: fixed;
right: 10px;
bottom: 40px;
height: 40px;
width: 40px;
border-radius: 100%;
text-align: center;
line-height: 40px;
cursor: pointer;
background: #ecd300;
background: radial-gradient(hsl(54, 100%, 50%), hsl(54, 100%, 40%));
font-size: 14px;
text-shadow: 0 -1px 0 #c3af07;
color: white;
border: 1px solid hsl(54, 100%, 20%);
z-index: 4;
outline: none;
box-shadow: inset 0 1px 0 hsl(54, 100%, 50%), 0 2px 0 hsl(54, 100%, 20%),
0 3px 0 hsl(54, 100%, 18%), 0 4px 0 hsl(54, 100%, 16%),
0 5px 0 hsl(54, 100%, 14%), 0 6px 0 hsl(54, 100%, 12%),
0 7px 0 hsl(54, 100%, 10%), 0 8px 0 hsl(54, 100%, 8%),
0 9px 0 hsl(54, 100%, 6%);
}
.violet_recognition_button:active {
box-shadow: inset 0 1px 0 hsl(54, 100%, 50%), 0 2px 0 hsl(54, 100%, 16%),
0 3px 0 hsl(54, 100%, 14%), 0 4px 0 hsl(54, 100%, 12%),
0 5px 0 hsl(54, 100%, 10%), 0 6px 0 hsl(54, 100%, 8%),
0 7px 0 hsl(54, 100%, 6%);
}
.violet_recognition_copy_board {
position: fixed;
top: 100px;
left: 100px;
width: 100px;
height: 80px;
display: none;
background: #fff;
}
.violet_recognition_copy_board > div {
background-color: #666;
color: #fff;
text-align: center;
}
问题
1.表单校验触发提示用户名和密码不能为空是因为chrome插件只改变了input输入框标签的值,并没有改变vue代码中存储的用户名密码,所以用户名密码还是为空,表单校验是基于vue中存储的用户名和密码来校验的,所以校验不通过。
解决方法 使用 JavaScript 原生事件的输入方式模拟用户输入,使用方法如下:
// bubbles设置true表示允许冒泡
function simulateInput(element, value) {
const inputEvent = new Event('input', { bubbles: true });
element.value = value;
element.dispatchEvent(inputEvent);
}
// 使用方法
simulateInput(document.querySelector('input[name="username"]'), 'your_username');
simulateInput(document.querySelector('input[name="password"]'), 'your_password');