Windows10 IE环境下Angular1.5.8发起请求遇权限拒绝问题求助
问题场景
我最近在基于 Angular 1.5.8 开发应用时碰到了一个诡异的问题:同一个函数分别在页面加载和剪贴板粘贴时触发,页面加载时一切正常,但在 Windows 10 的 IE 浏览器里(Chrome、Firefox 等其他浏览器完全没问题),剪贴板粘贴触发函数时就会报错:
- 直接用原生
XMLHttpRequest调用xhr.open('put', 'http://localhost:62631/api/PlantConsignee/', true)时,报 "invalid argument"; - 用 Angular 封装的
PlantConsignee.query方法时,报 "Access denied"。
报错栈如下:
at Anonymous function (http://localhost:62631/prodaction/script/node_modules Oh.min.js?ver=0.6.6688.17819:125:278) at n (http://localhost:62631/prodaction/script/node_modules Oh.min.js?ver=0.6.6688.17819:122:53) at Anonymous function (http://localhost:62631/prodaction/script/node_modules Oh.min.js?ver=0.6.6688.17819:119:255) at Anonymous function (http://localhost:62631/prodaction/script/node_modules Oh.min.js?ver=0.6.6688.17819:154: 10) at m.prototype.$eval (http://localhost:62631/prodaction/script/node_modules.min.js?ver=0.6.6688.17819:168: 336) at m.prototype.$digest (http://localhost:62631/prodaction/script/node_modules Oh.min.js?ver=0.6.6688.17819:165: 412) at m.prototype.$apply (http://localhost:62631/prodaction/script/node_modules.min.js?ver=0.6.6688.17819:169: 111) at Anonymous function (http://localhost:62631/prodaction/script/node_modules Oh.min.js?ver=0.6.6688.17819:299: 245) at w.event.dispatch (http://localhost:62631/prodaction/script/node_modules.min.js?ver=0.6.6688.17819:2:41706) at y.handle (http://localhost:62631/prodaction/script/node_modules Oh.min.js?ver=0.6.6688.17819:2:39718)
对应的核心代码是这样的:
function planttetst() { console.log("袟邪锌褉芯褋 蟹邪胁芯写芯胁"); var xhr = new XMLHttpRequest(); xhr.open('put', 'http://localhost:62631/api/PlantConsignee/', true); xhr.setRequestHeader('Content-Type', 'application/json; charset=utf-8'); var inp = JSON.stringify({ "pageNumber": 1, "pageSize": 9999, "Count": 9999, "Items": [{ "Id": 1, "PlantCode": "**", "Code": "BP00016238" }] }); xhr.send(inp); xhr.onreadystatechange = function () { var response = xhr.responseText; console.log("芯褌胁械褌 蟹邪胁芯写芯胁" + response.toString()); } PlantConsignee.query({ "pageNumber": 1, "pageSize": 9999, "Count": 9999, "Items": [{ "Id": 1, "PlantCode": "**", "Code": "BP00016238" }] }).$promise.then(function (response) { console.log("袟邪锌褉芯褋 蟹邪胁芯写芯胁 屑邪谢" + (new Date).toString()); alert("super"); }).catch(function (reason) { notifyService.error("袨褕懈斜泻邪 锌褉懈 蟹邪谐褉褍蟹泻械 褋锌褉邪胁芯褔薪懈泻邪 蟹邪胁芯写 planttetst1" + ((reason === undefined || reason === null || reason.data === undefined) ? "" : reason.data.message) + ". 袩芯胁褌芯褉懈褌械 锌芯锌褘褌泻褍 褔械褉械蟹 5 屑懈薪褍褌"); }); }
我已经试过给站点开完全管理员权限、把站点加入本地 Intranet 区域,甚至把 Angular 版本升到 1.5.9(更高版本会搞崩应用路径,没法用),但都没解决这个问题。
问题分析与解决办法
1. 最可能的原因:IE 剪贴板事件的上下文限制
IE 对剪贴板这类敏感操作的事件回调有特殊的安全限制——在 paste 事件的回调里直接发起异步 AJAX 请求,浏览器会因为安全策略拦截请求,就出现了"invalid argument"或"Access denied"的错误。而页面加载时触发函数,不在剪贴板事件的上下文里,所以没问题。
解决办法:用 setTimeout 脱离事件上下文
把请求逻辑包裹在 setTimeout 里,哪怕延迟 0ms 也能让请求脱离剪贴板事件的限制:
function planttetst() { // 把请求逻辑放到 setTimeout 里,脱离剪贴板事件上下文 setTimeout(function() { console.log("袟邪锌褉芯褋 蟹邪胁芯写芯胁"); var xhr = new XMLHttpRequest(); xhr.open('put', 'http://localhost:62631/api/PlantConsignee/', true); xhr.setRequestHeader('Content-Type', 'application/json; charset=utf-8'); var inp = JSON.stringify({ "pageNumber": 1, "pageSize": 9999, "Count": 9999, "Items": [{ "Id": 1, "PlantCode": "**", "Code": "BP00016238" }] }); xhr.send(inp); xhr.onreadystatechange = function () { var response = xhr.responseText; console.log("芯褌胁械褌 蟹邪胁芯写芯胁" + response.toString()); } PlantConsignee.query({ "pageNumber": 1, "pageSize": 9999, "Count": 9999, "Items": [{ "Id": 1, "PlantCode": "**", "Code": "BP00016238" }] }).$promise.then(function (response) { console.log("袟邪锌褉芯褋 蟹邪胁芯写芯胁 屑邪谢" + (new Date).toString()); alert("super"); }).catch(function (reason) { notifyService.error("袨褕懈斜泻邪 锌褉懈 蟹邪谐褉褍蟹泻械 褋锌褉邪胁芯褔薪懈泻邪 蟹邪胁芯写 planttetst1" + ((reason === undefined || reason === null || reason.data === undefined) ? "" : reason.data.message) + ". 袩芯胁褌芯褉懈褌械 锌芯锌褘褌泻褍 褔械褉械蟹 5 屑懈薪褍褌"); }); }, 0); }
2. 排查 URL 格式问题
IE 的原生 XHR 对 URL 格式比其他浏览器更挑剔,比如 URL 末尾的斜杠可能导致解析错误。你可以试试去掉 URL 末尾的斜杠,改成 http://localhost:62631/api/PlantConsignee:
xhr.open('put', 'http://localhost:62631/api/PlantConsignee', true);
3. 调整 Angular 的 HTTP 配置
Angular 1.x 在 IE 下有一些默认的兼容性问题,你可以在应用的配置里添加一些兼容设置:
angular.module('你的应用模块名', []) .config(['$httpProvider', function($httpProvider) { // 启用跨域支持(本地请求也可能受益) $httpProvider.defaults.useXDomain = true; delete $httpProvider.defaults.headers.common['X-Requested-With']; // 确保 PUT 请求的 Content-Type 设置正确 $httpProvider.defaults.headers.put['Content-Type'] = 'application/json; charset=utf-8'; }]);
4. 检查剪贴板事件的默认行为
如果绑定 paste 事件时没有阻止默认行为,可能会导致 IE 处于不稳定状态,影响后续请求。如果不需要默认的粘贴行为,可以在事件回调里先阻止默认行为:
// 假设你是这样绑定剪贴板事件的 document.querySelector('#你的输入框ID').addEventListener('paste', function(e) { e.preventDefault(); // 阻止默认粘贴 planttetst(); // 调用你的函数 });
验证步骤
建议按这个顺序尝试:
- 先试
setTimeout延迟执行的方案,这是解决 IE 剪贴板事件 AJAX 问题最常用的方法; - 如果没用,再修改 URL 去掉末尾斜杠;
- 最后检查 Angular 的 HTTP 配置是否正确。
内容的提问来源于stack exchange,提问作者katerinkadar

