当前位置: 首页 > news >正文

网站首页设计总结自助建站帮助网

网站首页设计总结,自助建站帮助网,人员证书查询,seo网站建设教程好久没做浏览器插件开发了,因为公司堡垒机,每次登录都要输入账号密码和验证码。太浪费时间了,就想着做一个右键菜单形式的扩展。 实现思路也很简单,在这里做下记录,方便下次开发参考。 一,先来了解下chro…

好久没做浏览器插件开发了,因为公司堡垒机,每次登录都要输入账号密码和验证码。太浪费时间了,就想着做一个右键菜单形式的扩展。

实现思路也很简单,在这里做下记录,方便下次开发参考。

一,先来了解下chrome扩展开发,必备文件。

manifest.json也叫清单文件。
先简单看下配置:

 //需要做C#兼职  或者浏览器插件兼职的请加我QQ:3388486286
{"manifest_version": 2,"name": "堡垒机自动化","version": "1.0","description": "右键菜单跳转到堡垒机页面,并自动登录","permissions": ["tabs", "contextMenus","webRequest","webRequestBlocking","https://127.0.0.4/*","http://127.0.0.4/*"],"background": {"scripts": ["background.js"]},"content_scripts": [{"matches": ["https://127.0.0.4/*","http://127.0.0.4/*"],"js": ["JS/log.js"]}],"web_accessible_resources": ["JS/config.json"],"icons": {"16": "Images/icon.png","48": "Images/icon.png","128": "Images/icon.png"}}

上述配置基本包含了插件开发的常用配置。现在简单介绍下每个配置的作用:

1.manifest_version :也就是版本的意思,你需要使用的插件版本,不过现在已经是第三版了,因为之前用过2开发,2和3的语法有差别,估本版本还是用到老版本的语法。新版本没时间去研究,反正都能用。

2.name :插件名称(自定义)

3.version : 当前插件的版本(自定义)

4.description : 插件描述

5.permissions :权限(你需要使用哪些API就需要对应的开通权限,也叫注册服务吧)

 "tabs", (该权限可以打开新的页面)
"contextMenus",(该权限可以右键创建新的菜单)
"webRequest",(该权限可以监听网络请求)
"webRequestBlocking",(该权限可以监听网络请求并且修改请求)
"https://127.0.0.4/*",(表示插件需要访问以 HTTPS 协议开头、IP 地址为 127.0.0.4 的所有页面或资源。这意味着插件将被允许在浏览器中与这些特定的 IP 地址和相关页面进行通信,无论是通过 HTTP 还是 HTTPS 访问。)
"http://127.0.0.4/*"(表示插件需要访问以 HTTP 协议开头、IP 地址为 127.0.0.4 的所有页面或资源。)
添加对应的地址作用:这意味着插件将被允许在浏览器中与这些特定的 IP 地址和相关页面进行通信,无论是通过 HTTP 还是 HTTPS 访问。
  1. "background":
    { "scripts": ["background.js"] }该脚本会一直运行监听。

具体含义如下:

"background":表示指定插件的后台脚本。
"scripts":表示指定后台脚本文件的路径。
"background.js":表示插件的后台页面脚本文件名为 "background.js"。
通过将脚本文件名添加到 "scripts" 数组中,你可以告诉浏览器插件在加载时要运行哪个脚本文件作为后台页面。这个后台页面脚本通常用于处理插件的核心功能、与浏览器 API 进行交互以及响应来自其他插件部分(如内容脚本或浏览器操作栏)的事件。

7.content_scripts

 //content_scripts  为业务JS注入,就是你要操作前端页面元素的JS  其中matches表示你JS要注入到哪些页面地址。"content_scripts": [{"matches": ["https://127.0.0.4/*","http://127.0.0.4/*"],"js": ["JS/log.js"]   //需要注入的Js文件}]

8.web_accessible_resources:这里面往往放些静态全局的配置文件。
9.icons:图标文件。

二 、先说下background.js的思路。

1.先注册右键菜单,这样你右键浏览器,就可以看到自己的扩展程序了。

chrome.contextMenus.create({title:"堡垒机自动化",onclick:function(){console.log('准备跳转..')//跳转指定页面chrome.tabs.create({url:'https://127.0.0.4/index.php/login'},(tab)=>{console.log('跳转成功..')console.log(tab)//执行业务代码 注入JSchrome.tabs.executeScript(tab.id,{ file: 'JS/content_script.js'})})}})

其中executeScript也是注入JS的一种方式,这种方式比较灵活,这种注入方式也可以和页面元素进行交互。

2.跳转到指定页面后,我们需要输入账号和密码,这块业务逻辑就写在content_script.js


var credentials = {};// 读取配置文件并存储到全局对象
async function getConfig() {try {const response = await fetch(chrome.runtime.getURL('JS/config.json'));credentials = await response.json();console.log(credentials); // 打印全局对象// 调用填充函数fillCredentials();} catch (error) {console.error('Error reading config file:', error);}
} // 在页面上填充账号和密码
function fillCredentials() {document.querySelector("#pwd_username").value = credentials.username;document.querySelector("#pwd_pwd").value = credentials.password;//GetAccessToken();}

这里我们调用下getConfig()方法,进行配置文件读取,然后赋值给全局变量存储。,然后调用fillCredentials()进行账号密码赋值。

3.验证码识别,并赋值登录。
我们验证码就是一个4位字母图片,这块逻辑我是直接调用百度API实现的,本来想着自己后端实现,但是用了下第三方库,要么响应时间太久了,要么就是识别不准确。百度API直接帮你解决了这2个麻烦。但是要收费,我只用了100次的免费体验。
现在说下具体实现思路吧,本来想着直接前端发送请求识别,但是浏览器有同源策略,跨域了…这个最终还是要用到后端服务,于是就用了后端API去做图片识别功能了。

3.1先获取验证码图片的url地址。
这里我们在background.js中添加网络监听,因为图片url有固定格式,很好匹配。具体代码如下:

// 声明一个变量用于保存监听器
let requestListener;
// 启动网络请求监听器requestListener = function(details) {// 检查请求地址是否以指定的 URL 开头if (details.url.startsWith('https://127.0.0.4/captcha/')) {// 提取图片地址const imageUrl = details.url;// 输出图片地址console.log('图片地址:', imageUrl);// 在这里可以进行进一步的处理sendImageURLToContentScript(imageUrl);}}chrome.webRequest.onBeforeRequest.addListener(requestListener,{ urls: ['https://127.0.0.4/captcha/*'] }, // 监听以指定 URL 开头的请求['blocking']);

通过 chrome.webRequest.onBeforeRequest.addListener开启网络监听,当匹配到指定url开头的信息后,就代表该url是图片url,然后把imageUrl传给content_script.js
这里声明下:
background.js是不能直接和操作的页面通信的,background.js主要操作浏览器提供的API。实际操作Dom元素需要通过业务JS去操作。这里的业务JS就是content_script.js
那么background.jscontent_script.js如何通信呢,看代码:

 // 在background.js中获取到图片地址后,延迟1秒发送消息给业务 JSfunction sendImageURLToContentScript(imageUrl) {chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) {if (tabs.length > 0) {const tabId = tabs[0].id;setTimeout(function() {chrome.tabs.sendMessage(tabId, { imageUrl: imageUrl }, function(response) {// 在收到业务 JS 的响应后进行处理(可选)console.log('收到业务 JS 的响应:', response);});}, 500); // 延迟1秒后发送消息}});}

通过 chrome.tabs.sendMessage 发送消息。

// 业务 JS 接收消息,并进行处理
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {// 接收到来自 background.js 的消息if (request.imageUrl) {const imageUrl = request.imageUrl;// 在这里进行业务逻辑处理,使用获取到的图片地址console.log('收到来自 background.js 的图片地址:', imageUrl);GetCode(imageUrl);//GetBase64(imageUrl);// 可以通过 sendResponse 向 background.js 发送响应消息(可选)sendResponse({ message: '已收到图片地址' });}});

通过chrome.runtime.onMessage.addListener接收消息
这样就实现了background.jscontent_script.js的通信。
至于为什么要延迟500毫秒再发送,是因为我们点击右键后,content_script.js才注入到页面,而再这时候,background.js已经再运行了。所有延迟会再发送消息,这样可以避免content_script.js那边接收不到消息。

3.2业务JS发送imageUrl给后端api进行图像验证码识别

 function GetCode(imageUrl){fetch(credentials.getcode_url, {method: "POST",headers: {"Content-Type": "application/json"},body: JSON.stringify(imageUrl)}).then(response => response.text()).then(result => {let data = JSON.parse(result);// 获取 words_result 字段的值  let wordsResult = data.words_result;// 获取数组中第一个元素的 words 字段的值let words = wordsResult[0].words;console.log(words);  // 输出: "code"//赋值codedocument.querySelector("#pwd_captcha").value = words;//点击登录document.querySelector("#sign-box > form.form-vertical.login-content.active > div.submit-row > button").click();}).catch(error => {console.error("请求出错:", error);});}

好了这样就实现了验证码识别,然后赋值登录操作呢。

三、给出所有相关代码

config.json:

{"username": "username","password": "password","client_id":"FrktGAjFVjGv9SSA6S3","client_secret":"IFL6FbU6tuFrPoCjaYnvvRrCGd","token_url":"https://aip.baidubce.com/oauth/2.0/token","getcode_url":"http://localhost:5270/api/CodeIdentity"
}

background.js


// 声明一个变量用于保存监听器
let requestListener;
// 启动网络请求监听器requestListener = function(details) {// 检查请求地址是否以指定的 URL 开头if (details.url.startsWith('https://127.0.0.4/captcha/')) {// 提取图片地址const imageUrl = details.url;// 输出图片地址console.log('图片地址:', imageUrl);// 在这里可以进行进一步的处理sendImageURLToContentScript(imageUrl);}}chrome.webRequest.onBeforeRequest.addListener(requestListener,{ urls: ['https://127.0.0.4/captcha/*'] }, // 监听以指定 URL 开头的请求['blocking']);// 在background.js中获取到图片地址后,延迟1秒发送消息给业务 JSfunction sendImageURLToContentScript(imageUrl) {chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) {if (tabs.length > 0) {const tabId = tabs[0].id;setTimeout(function() {chrome.tabs.sendMessage(tabId, { imageUrl: imageUrl }, function(response) {// 在收到业务 JS 的响应后进行处理(可选)console.log('收到业务 JS 的响应:', response);});}, 500); // 延迟1秒后发送消息}});}chrome.contextMenus.create({title:"堡垒机自动化",onclick:function(){console.log('准备跳转..')//跳转指定页面chrome.tabs.create({url:'https://127.0.0.4/index.php/login'},(tab)=>{console.log('跳转成功..')console.log(tab)//执行业务代码 注入JSchrome.tabs.executeScript(tab.id,{ file: 'JS/content_script.js'})})}})// // 启动网络请求监听器
// chrome.webRequest.onBeforeRequest.addListener(
//     function(details) {
//       // 检查请求地址是否以指定的 URL 开头
//       if (details.url.startsWith('https://127.0.0.4/captcha/')) {
//         // 提取图片地址
//         const imageUrl = details.url;//         // 输出图片地址
//         console.log('图片地址:', imageUrl);//         // 在这里可以进行进一步的处理
//         sendImageURLToContentScript(imageUrl);
//       }
//     },
//     { urls: ['https://127.0.0.4/captcha/*'] }, // 监听以指定 URL 开头的请求
//     ['blocking']
//   );// 在background.js中获取到图片地址后,延迟1秒发送消息给业务 JS
// function sendImageURLToContentScript(imageUrl) {
//     chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) {
//       if (tabs.length > 0) {
//         const tabId = tabs[0].id;//         setTimeout(function() {
//           chrome.tabs.sendMessage(tabId, { imageUrl: imageUrl }, function(response) {
//             // 在收到业务 JS 的响应后进行处理(可选)
//             console.log('收到业务 JS 的响应:', response);
//                  // 移除监听器
//         chrome.webRequest.onBeforeRequest.removeListener(requestListener);
//           });
//         }, 100); // 延迟1秒后发送消息
//       }
//     });
//   }// 开始监听网络请求
//startRequestListener();

content_script.js

// 业务 JS 接收消息,并进行处理
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {// 接收到来自 background.js 的消息if (request.imageUrl) {const imageUrl = request.imageUrl;// 在这里进行业务逻辑处理,使用获取到的图片地址console.log('收到来自 background.js 的图片地址:', imageUrl);GetCode(imageUrl);//GetBase64(imageUrl);// 可以通过 sendResponse 向 background.js 发送响应消息(可选)sendResponse({ message: '已收到图片地址' });}});var credentials = {};// 读取配置文件并存储到全局对象
async function getConfig() {try {const response = await fetch(chrome.runtime.getURL('JS/config.json'));credentials = await response.json();console.log(credentials); // 打印全局对象// 调用填充函数fillCredentials();} catch (error) {console.error('Error reading config file:', error);}
} // 在页面上填充账号和密码
function fillCredentials() {document.querySelector("#pwd_username").value = credentials.username;document.querySelector("#pwd_pwd").value = credentials.password;//GetAccessToken();}/*** 使用 AK,SK 生成鉴权签名(Access Token)* @returns 鉴权签名信息(Access Token)*/
//  function GetAccessToken() {
//     const url = credentials.token_url;
//     const data = {
//       grant_type: 'client_credentials',
//       client_id: credentials.client_id,
//       client_secret: credentials.client_secret
//     };//     const requestOptions = {
//       method: 'POST',
//       mode: 'cors',
//       headers: { 'Content-Type': 'application/json' },
//       body: JSON.stringify(data)
//     };//     return fetch(url, requestOptions)
//       .then(response => {
//         if (!response.ok) {
//           throw new Error('Network response was not ok');
//         }
//         return response.json();
//       })
//       .then(data => {
//         console.log(data);
//         console.log(data.access_token);
//         return data.access_token;
//       })
//       .catch(error => {
//         console.error(error);
//       });
//   }function GetCode(imageUrl){fetch(credentials.getcode_url, {method: "POST",headers: {"Content-Type": "application/json"},body: JSON.stringify(imageUrl)}).then(response => response.text()).then(result => {let data = JSON.parse(result);// 获取 words_result 字段的值  let wordsResult = data.words_result;// 获取数组中第一个元素的 words 字段的值let words = wordsResult[0].words;console.log(words);  // 输出: "code"//赋值codedocument.querySelector("#pwd_captcha").value = words;//点击登录// document.querySelector("#sign-box > form.form-vertical.login-content.active > div.submit-row > button").click();}).catch(error => {console.error("请求出错:", error);});}//图片转base64
//   function getFileContentAsBase64(path) {
//     return new Promise((resolve, reject) => {
//       fetch(path)
//         .then(response => response.arrayBuffer())
//         .then(buffer => {
//           const bytes = new Uint8Array(buffer);
//           let binary = '';
//           for (let i = 0; i < bytes.byteLength; i++) {
//             binary += String.fromCharCode(bytes[i]);
//           }
//           const base64 = btoa(binary);
//           resolve(base64);
//         })
//         .catch(error => reject(error));
//     });
//   }// function GetBase64(captchaUrl)
// {
// // 使用fetch函数获取验证码图片的二进制数据
// fetch(captchaUrl)
//   .then(response => response.blob())
//   .then(blob => {
//     // 创建一个FileReader对象来读取blob数据
//     const reader = new FileReader();
//     reader.onloadend = function() {
//       // 读取完成后,将二进制数据转换为Base64编码
//       const base64 = reader.result.split(',')[1];//       // 调用getFileContentAsBase64方法进行后续处理
//       getFileContentAsBase64(base64)
//         .then(result => {
//           console.log("base64:",result);
//         })
//         .catch(error => {
//           console.error(error);
//         });
//     };
//     reader.readAsDataURL(blob);
//   })
//   .catch(error => {
//     console.error(error);
//   });// }//识别验证码// 获取配置并存储到全局对象
getConfig();

后端代码:

using CodeIdentify.Servers;var builder = WebApplication.CreateBuilder(args);// Add services to the container.builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddScoped<IBaiDuCodeIdentity, BaiDuCodeIdentityRepostoty>();
builder.Services.AddCors(options => {options.AddPolicy("AllowAll", builder =>{builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader();});
});var app = builder.Build();app.UseCors("AllowAll");
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{app.UseSwagger();app.UseSwaggerUI();
}app.UseAuthorization();app.MapControllers();app.Run();
namespace CodeIdentify.Servers
{public interface IBaiDuCodeIdentity{Task<string> GetAccessTokenAsync();Task<string> GetCodeAsync(string base64);Task DownloadImageAsync(string url , string saveDirectory);string GetFileContentAsBase64(string path);void DeleteImage(string path);}
}
using Microsoft.OpenApi.Models;
using Newtonsoft.Json;
using RestSharp;
using System.Net;namespace CodeIdentify.Servers
{public class BaiDuCodeIdentityRepostoty : IBaiDuCodeIdentity{public void DeleteImage(string path){try{// 获取指定文件夹中的所有图片文件string[] imageFiles = Directory.GetFiles(path, "*.jpg");foreach (string file in imageFiles){// 删除文件File.Delete(file);Console.WriteLine($"已删除文件: {file}");}Console.WriteLine("所有图片文件已删除。");}catch (Exception ex){throw new Exception(ex.Message);Console.WriteLine($"删除图片文件时出错:{ex.Message}");}}public async Task DownloadImageAsync(string imageUrl, string saveDirectory){// 创建自定义的 HttpClientHandler,并禁用证书验证var handler = new HttpClientHandler(){ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => true};// 创建 HttpClient 实例,并使用自定义的 HttpClientHandlerusing (HttpClient httpClient = new HttpClient(handler)){try{// 发送 GET 请求并获取响应消息HttpResponseMessage response = await httpClient.GetAsync(imageUrl);response.EnsureSuccessStatusCode();// 从响应消息中获取图片内容byte[] imageBytes = await response.Content.ReadAsByteArrayAsync();// 创建文件保存路径Directory.CreateDirectory(saveDirectory);string savePath = Path.Combine(saveDirectory, "image.jpg"); // 要保存的文件名// 将图片内容保存到本地文件File.WriteAllBytes(savePath, imageBytes);Console.WriteLine("图片下载完成。");}catch (Exception ex){throw new  Exception($"图片下载失败:{ex.Message}");Console.WriteLine($"图片下载失败:{ex.Message}");}}}public async Task<string> GetAccessTokenAsync(){try{var client = new RestClient($"https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=FrktGAjFVjSSA6S3Tcs0f&client_secret=IFL6FbU6rPoCjaSiKjMLYnvvRrCGd");var request = new RestRequest(String.Empty, Method.Post);request.AddHeader("Content-Type", "application/json");request.AddHeader("Accept", "application/json");var body = @"";request.AddParameter("application/json", body, ParameterType.RequestBody);var response = await client.ExecuteAsync(request);var result = JsonConvert.DeserializeObject<dynamic>(response.Content??"");Console.WriteLine(result?.access_token.ToString());return result?.access_token.ToString()??"";}catch (Exception e){throw new Exception($"可能次数用完了:{e.Message}");}}public async Task<string> GetCodeAsync(string base64){var token = await GetAccessTokenAsync();var client = new RestClient($"https://aip.baidubce.com/rest/2.0/ocr/v1/accurate_basic?access_token={token}");var request = new RestRequest(String.Empty, Method.Post);request.AddHeader("Content-Type", "application/x-www-form-urlencoded");request.AddHeader("Accept", "application/json");// image 可以通过 GetFileBase64Content('C:\fakepath\captcha.png') 方法获取request.AddParameter("image", base64);var  response = await client.ExecuteAsync(request);Console.WriteLine(response.Content);return response.Content??"";}public string GetFileContentAsBase64(string path){using (FileStream filestream = new FileStream(path, FileMode.Open)){byte[] arr = new byte[filestream.Length];filestream.Read(arr, 0, (int)filestream.Length);string base64 = Convert.ToBase64String(arr);return base64;}}}
}
using CodeIdentify.Servers;
using Microsoft.AspNetCore.Mvc;namespace CodeIdentify.Controllers
{[Route("api/[controller]")][ApiController]public class CodeIdentityController : ControllerBase{private readonly IBaiDuCodeIdentity _baiDuCodeIdentity;public CodeIdentityController(IBaiDuCodeIdentity baiDuCodeIdentity) {_baiDuCodeIdentity = baiDuCodeIdentity;}[HttpPost]public async Task<IActionResult> GetCode([FromBody] string url) {string path = "Images\\image.jpg";string deletepath = "Images";await _baiDuCodeIdentity.DownloadImageAsync(url, "Images");string code = await _baiDuCodeIdentity.GetCodeAsync(_baiDuCodeIdentity.GetFileContentAsBase64(path));if(string.IsNullOrWhiteSpace(code)) return BadRequest("空字符串,识别有误");_baiDuCodeIdentity.DeleteImage(deletepath);return Ok(code);} }
}
http://www.yayakq.cn/news/931338/

相关文章:

  • 一般网站建设大概需要多少钱个人网站带后台源码
  • 淘宝网站怎么做会话保持的个人中心页面
  • seo管理系统培训运营百度推广seo效果怎么样
  • 网站建设的服务怎么样东莞百度快速排名
  • wordpress为什么那么卡企业网站优化方案范本
  • 汉中建站公司虚拟主机和云服务器
  • 网站建设的必要性分析做警员编号网站
  • 重庆seowhy整站优化网页版qq空间登录
  • 如何建一个简单的网站制作网页的网站叫什么
  • 浙江省住房和建设厅网站finecms
  • dedecms模板站源码wordpress 绿色公益主题
  • 用网站做的人工智能wordpress 工作流程
  • 青州做网站的网络公司网站备案负责人变更
  • 网站开发 入门电子商务网站设计
  • 一诺网站建设简述企业网站建设实施的步骤
  • 企业网站的功能有哪些深圳住房建设部官方网站
  • 网站建站需求做网站用买服务器码
  • 机关网站建设存在的问题wordpress接入官方号
  • 网站建设进度表模板传奇合成版2合1雷霆版手游
  • 中国建设工程信息网站新加坡网络公司排名
  • 网站建设文字教程视频南昌做公司网站哪家好
  • 服务器上安装wordpress深圳seo推广
  • 建设营销型网站有哪些步骤工程建设标准网站
  • 网站怎么放到服务器上襄阳seo推广
  • 怎样说服老板做网站友情链接是免费的吗
  • 台州做网站多少钱建设网站企业专业服务
  • 起域名网站wordpress登陆新域名
  • 做网站的软件叫什么软件免费的网页网站
  • 北京网站建设熊掌号网页设计案例分析ppt
  • 展示型网站有哪些内容alexa排名全球前50网站