使用XMLHttpRequest手动设置Accept-Time头为何总是出现undefined?
解决XMLHttpRequest设置Accept-Time请求头出现undefined前缀的问题
问题分析
你遇到的情况是,手动设置Accept-Time请求头时,最终发送的头值会带上undefined, 前缀,导致服务器返回403错误。这是因为页面环境(网站自身的混淆脚本或浏览器拦截逻辑)已经预先给XMLHttpRequest添加了一个值为undefined的Accept-Time头,而XMLHttpRequest的setRequestHeader方法默认采用追加模式——重复设置同一个头时,新值会被逗号分隔追加到旧值之后,而非直接覆盖。
解决方案
方案1:使用独立iframe中的XMLHttpRequest构造函数
页面中的脚本通常只会拦截当前window对象下的XMLHttpRequest,通过创建一个独立的iframe,从iframe中获取未被篡改的XMLHttpRequest构造函数,就能避开原有拦截逻辑,直接设置纯净的请求头:
var serverTime = Date.now().toString(), post_data = 'token=......'; // 创建隐藏的iframe var iframe = document.createElement('iframe'); iframe.style.display = 'none'; document.body.appendChild(iframe); // 从iframe获取原生XMLHttpRequest var NativeXHR = iframe.contentWindow.XMLHttpRequest; var xhr = new NativeXHR(); xhr.open('POST', 'https://......', false); xhr.setRequestHeader('Accept', 'application/json, text/javascript, */*; q=0.01'); xhr.setRequestHeader('Accept-Time', serverTime); xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded; charset=UTF-8'); xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); xhr.send(post_data); // 用完可以移除iframe document.body.removeChild(iframe);
方案2:改用Fetch API发送请求
Fetch API的Headers对象支持直接覆盖默认头,不会自动追加,也能避免原有XHR拦截的问题:
var serverTime = Date.now().toString(), post_data = 'token=......'; fetch('https://......', { method: 'POST', headers: new Headers({ 'Accept': 'application/json, text/javascript, */*; q=0.01', 'Accept-Time': serverTime, 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'X-Requested-With': 'XMLHttpRequest' }), body: post_data, credentials: 'include' // 如果请求需要携带Cookie,加上这一行 }) .then(response => { // 处理响应 console.log(response); }) .catch(error => { console.error(error); });
验证
发送请求后,在DevTools的Network面板中查看请求头,确认Accept-Time的值已变为纯时间戳字符串,此时服务器应该会返回正常响应,而非403。
内容的提问来源于stack exchange,提问作者Scott Paang
相关产品推荐
相关产品推荐

