好久没做浏览器插件开发了,因为公司堡垒机,每次登录都要输入账号密码和验证码。太浪费时间了,就想着做一个右键菜单形式的扩展。
实现思路也很简单,在这里做下记录,方便下次开发参考。
一,先来了解下chrome扩展开发,必备文件。
manifest.json
也叫清单文件。
先简单看下配置:
//需要做C#兼职 或者浏览器插件兼职的请加我QQ:3388486286{ "manifest_version": 2, "name": "堡垒机自动化", "version": "1.0", "description": "右键菜单跳转到堡垒机页面,并自动登录", "permissions": [ "tabs", "contextMenus", "webRequest", "webRequestBlocking", "https://127.0.0.4// 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" //赋值code document.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/swashbucklebuilder.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 实例,并使用自定义的 HttpClientHandler using (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); } }}
来源地址:https://blog.csdn.net/csdn2990/article/details/132476200