您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
绕过绿盾验证,恢复积分查看
当前为
// ==UserScript== // @name Bypass verification // @namespace http://tampermonkey.net/ // @version 0.2 // @description 绕过绿盾验证,恢复积分查看 // @author Brian // @match http://oa.microvideo.cn/* // @grant none // @run-at document-start // @license MIT // ==/UserScript== (function () { "use strict"; // Store the original createElement method const originalCreateElement = document.createElement; // Override createElement to intercept script creation document.createElement = function (tagName) { // Create the element using the original method const element = originalCreateElement.apply(document, arguments); // Only intercept script elements if (tagName.toLowerCase() === "script") { // Store the original setter const originalSrcSetter = Object.getOwnPropertyDescriptor( HTMLScriptElement.prototype, "src" ).set; // Override the src property Object.defineProperty(element, "src", { set: function (value) { // Check if this is the local verification request if (value && value.includes("127.0.0.1:50018")) { console.log( "[Bypass] Intercepted local verification request:", value ); // Call the original setter with the URL to maintain script behavior originalSrcSetter.call(this, value); // Override the onerror handler to prevent 403 redirect setTimeout(() => { this.onerror = function (e) { console.log("[Bypass] Prevented redirect to 403 page"); // Create a mock response const mockResponse = { result: window.be.encode( JSON.stringify({ data: [ { UserNo: window._t.lvdunUserNo, // Use the same UserNo from the app }, ], }) ), }; // If there's a success handler defined, call it with our mock response if (typeof window.localHandler === "function") { console.log( "[Bypass] Calling success handler with mock response" ); window.localHandler(mockResponse); } // Make sure loading state is completed if (window.z && typeof window.z.done === "function") { window.z.done(); } if (window.kt && window.kt.commit) { window.kt.commit("loading/OPPEN_LOADING", { show: false }); } return true; // Prevent the default error behavior }; // Also override onload to ensure our mock response is used this.onload = function () { console.log( "[Bypass] Script loaded, ensuring mock response is used" ); // The script might define its own localHandler, so we'll wait a bit and then check setTimeout(() => { if (typeof window.localHandler === "function") { const mockResponse = { result: window.be.encode( JSON.stringify({ data: [ { UserNo: window._t.lvdunUserNo, }, ], }) ), }; console.log( "[Bypass] Calling success handler with mock response" ); window.localHandler(mockResponse); } }, 100); }; }, 0); return; } // For all other scripts, use the original setter originalSrcSetter.call(this, value); }, get: function () { return Object.getOwnPropertyDescriptor( HTMLScriptElement.prototype, "src" ).get.call(this); }, }); } return element; }; // Create a backup method to handle the AJAX request if it's made directly const originalAjax = window.ve && window.ve.ajax; if (originalAjax) { window.ve.ajax = function (options) { if (options.url && options.url.includes("127.0.0.1:50018")) { console.log("[Bypass] Intercepted AJAX request to local service"); // Create a mock response const mockResponse = { result: window.be.encode( JSON.stringify({ data: [ { UserNo: window._t.lvdunUserNo, }, ], }) ), }; // Call the success callback with our mock response if (options.success && typeof options.success === "function") { setTimeout(() => { options.success(mockResponse); }, 50); } // Don't actually make the AJAX request return; } // For all other AJAX requests, use the original method return originalAjax.apply(this, arguments); }; } // Add a global error handler for the specific script window.addEventListener( "error", function (event) { if ( event.target && event.target.src && event.target.src.includes("127.0.0.1:50018") ) { console.log("[Bypass] Caught error event for local service script"); event.preventDefault(); event.stopPropagation(); return true; } }, true ); // 保存原始的 XMLHttpRequest.prototype.open 和 send 方法 const originalXhrOpen = XMLHttpRequest.prototype.open; const originalXhrSend = XMLHttpRequest.prototype.send; // 定义目标URL需要包含的子字符串 const targetUrlSubstring = '/prod-api/attendancePointsStatistics/getPointsByUserId?userId='; // 重写 XMLHttpRequest.prototype.open 方法 XMLHttpRequest.prototype.open = function(method, url) { // 在XHR对象上存储请求方法和URL,以便在 send 方法中检查 this._requestMethod = method; this._requestUrl = url; // console.log('[油猴脚本] XHR open:', method, url); // 用于调试 // 调用原始的 open 方法 return originalXhrOpen.apply(this, arguments); }; // 重写 XMLHttpRequest.prototype.send 方法 XMLHttpRequest.prototype.send = function() { // 检查当前请求是否是我们的目标请求 (GET方法且URL包含目标子字符串) // 添加 typeof this._requestUrl === 'string' 确保 _requestUrl 是字符串类型 if (this._requestMethod && this._requestMethod.toUpperCase() === 'GET' && this._requestUrl && typeof this._requestUrl === 'string' && this._requestUrl.includes(targetUrlSubstring)) { console.log('[油猴脚本] 匹配到目标XHR请求 (based on includes):', this._requestUrl); // 保存原始的 onreadystatechange 回调函数 (如果存在) const originalOnReadyStateChange = this.onreadystatechange; // 设置新的 onreadystatechange 回调函数 this.onreadystatechange = function() { // 当请求完成 (readyState === 4) if (this.readyState === 4) { // 再次确认URL (使用 responseURL,它会包含重定向后的最终URL) // 并检查请求是否成功 (status 200-299) const currentUrl = this.responseURL || this._requestUrl; // 再次使用 String.includes() 判断 currentUrl // 添加 typeof currentUrl === 'string' 确保 currentUrl 是字符串类型 if (this.status >= 200 && this.status < 300 && currentUrl && typeof currentUrl === 'string' && currentUrl.includes(targetUrlSubstring)) { console.log('[油猴脚本] 目标XHR请求完成:', currentUrl, '状态:', this.status); try { // 获取原始的响应文本 let originalResponseText = this.responseText; // 解析JSON数据 let responseData = JSON.parse(originalResponseText); // 检查JSON结构是否符合预期,并且 data.type 字段存在 if (responseData && responseData.data && responseData.data.hasOwnProperty('type')) { console.log('[油猴脚本] 原始 data.type:', responseData.data.type); // 修改 data.type 的值为 "1" (字符串类型) responseData.data.type = "1"; console.log('[油猴脚本] 修改后 data.type:', responseData.data.type); // 将修改后的JavaScript对象转换回JSON字符串 const modifiedResponseText = JSON.stringify(responseData); // 使用 Object.defineProperty 重新定义 responseText 和 response 属性 Object.defineProperty(this, 'responseText', { value: modifiedResponseText, writable: false, configurable: true }); if (this.responseType === 'json') { Object.defineProperty(this, 'response', { value: responseData, writable: false, configurable: true }); } else if (this.responseType === '' || this.responseType === 'text') { Object.defineProperty(this, 'response', { value: modifiedResponseText, writable: false, configurable: true }); } else { Object.defineProperty(this, 'response', { value: (this.responseType === 'json') ? responseData : modifiedResponseText, writable: false, configurable: true }); } console.log('[油猴脚本] Response 属性已为', currentUrl, '重新定义'); } else { console.warn('[油猴脚本] 响应数据中未找到 data.type 或结构不符:', currentUrl, responseData); } } catch (e) { console.error('[油猴脚本] 处理或修改响应时出错:', currentUrl, e); } } else { // console.log('[油猴脚本] XHR请求完成,但非目标请求、重定向后不匹配或请求失败:', currentUrl, '状态:', this.status, '包含判断:', (currentUrl && typeof currentUrl === 'string' && currentUrl.includes(targetUrlSubstring))); } } // 无论如何,都调用原始的 onreadystatechange 回调 (如果存在) if (originalOnReadyStateChange) { return originalOnReadyStateChange.apply(this, arguments); } }; } // 调用原始的 send 方法,并传递参数 return originalXhrSend.apply(this, arguments); }; console.log("[Bypass] Local verification bypass script initialized"); })();