如果你 cloudflare 人机验证总是失败
在我的网络环境下(山东济南移动),加载 cloudflare 人机验证常常需要验证很久然后失败.
在网络请求中可以看到失败的请求用时总是 5s、10s 与 15s,非常准时间,看来是网络请求在客户端一侧被掐断了.打断点进去看到请求用的是 XMLHttpRequest,设置了 timeout 参数,若加载过慢会自动掐断.将 timeout 取消就可以解决问题.
于是我让 AI 写了个油猴脚本.安装后 cloudflare 小组件的所有请求都不会有 timeout.等待约 30s 就可以通过.
我不知道其他人是什么情况,反正 it works on my machine.
// ==UserScript==
// @name Choudflare 人机验证辅助脚本
// @namespace https://mrpython.top/
// @version 1.0
// @description 劫持 XMLHttpRequest,在 send 时对特定链接设置 timeout 为 undefined
// @match https://challenges.cloudflare.com/cdn-cgi/challenge-platform/*
// @run-at document-start
// @grant unsafeWindow
// ==/UserScript==
(function() {
'use strict';
// ================= 配置区 =================
// 设置你需要拦截的特定链接特征(可以是完整 URL,也可以是部分路径关键字)
const TARGET_URL_FEATURE = '';
// ==========================================
// 获取网页真实的 window 对象,防止沙盒隔离
const win = unsafeWindow || window;
const XHR = win.XMLHttpRequest;
if (!XHR) {
console.warn('[XHR Hook] 当前环境不支持 XMLHttpRequest');
return;
}
// 保存原生方法的引用,防止被覆盖后丢失
const originalOpen = XHR.prototype.open;
const originalSend = XHR.prototype.send;
/**
* 1. 劫持 open 方法
* 目的:在请求初始化时,捕获并记录请求的 URL 地址
*/
XHR.prototype.open = function(method, url, async, user, password) {
// 将 url 挂载到当前 XHR 实例的自定义属性上
// 使用 String() 是为了兼容某些库传入 URL 对象的情况
this._hook_url = url ? String(url) : '';
// 透传所有参数,调用原生 open 方法
return originalOpen.apply(this, arguments);
};
/**
* 2. 劫持 send 方法
* 目的:在请求真正发送前,检查 URL 并修改 timeout 属性
*/
XHR.prototype.send = function(body) {
const url = this._hook_url;
// 判断当前请求是否匹配目标链接
if (url && url.includes(TARGET_URL_FEATURE)) {
console.log(`%c[XHR Hook] 拦截到目标请求: ${url}`, 'color: #00ff00; font-weight: bold;');
console.log(`[XHR Hook] 修改前 timeout: ${this.timeout}`);
// 按照你的要求,将 timeout 设置为 undefined
this.timeout = undefined;
console.log(`[XHR Hook] 修改后 timeout: ${this.timeout}`);
}
// 透传参数,调用原生 send 方法真正发送请求
return originalSend.apply(this, arguments);
};
console.log('%c[XHR Hook] XMLHttpRequest 劫持已就绪!', 'color: #0088ff; font-weight: bold;');
})();