如何修改Ajax的src属性且不发起新请求?解决iframe认证请求异常
咱们先拆解下你遇到的两个核心问题:
为什么会出现无认证头的GET请求(返回401)?
当你执行$('#dashboard').attr('src', 'https://mysystem.xxxx');这行代码时,浏览器会单独发起一个全新的GET请求去加载这个iframe的源地址——这个请求和你之前的AJAX请求完全是独立的,根本不会继承AJAX里设置的Authorization头或者withCredentials配置。这是浏览器的同源策略和iframe加载机制决定的,所以这个无认证的请求自然会被目标系统拒绝,返回401。
为什么移除src行后静态资源会404?
你通过AJAX拿到HTML内容后,直接塞进了iframe的<html>标签里,但此时iframe的src是空的,浏览器会把当前页面的域名作为基准,去请求那些相对路径的静态资源(比如/css/style.css会被解析成当前页面域名下的路径),而不是目标系统的域名,所以肯定找不到对应的资源,返回404。
针对这个问题的几种解决思路
思路1:利用Cookie共享认证(优先推荐)
既然你的AJAX请求已经设置了withCredentials: true,如果目标系统的CORS配置正确(返回Access-Control-Allow-Credentials: true,且允许当前域名跨域),那么AJAX请求成功后,目标系统返回的认证Cookie会被浏览器保存。这时候你可以直接设置iframe的src为目标地址,浏览器会自动携带这个Cookie,不需要手动加Authorization头:
$.ajax({ url: 'https://mysystem.xxxx/', beforeSend: function(xhr) { xhr.withCredentials = true; xhr.setRequestHeader("Authorization", "Basic Z2Vxxxxxxxxxxx=="); }, success: function() { // 此时Cookie已保存,直接加载iframe即可 $('#dashboard').attr('src', 'https://mysystem.xxxx'); } });
注意:目标系统需要支持基于Cookie的认证,并且Cookie的域、路径等配置要允许当前页面的域名访问。
思路2:修正静态资源的绝对路径
如果你必须用AJAX获取HTML再塞进iframe,那需要把返回的HTML里所有相对路径的静态资源,都替换成目标系统的绝对路径。比如:
- 把
<link href="/css/main.css">改成<link href="https://mysystem.xxxx/css/main.css"> - 把
<script src="/js/app.js">改成<script src="https://mysystem.xxxx/js/app.js"> - 图片的
src同理处理
你可以在AJAX的success回调里用正则表达式批量替换这些路径:
success: function(data) { // 替换所有相对路径为绝对路径 const processedData = data.replace(/(src|href)="\/(.*?)"/g, '$1="https://mysystem.xxxx/$2"'); $('#dashboard').contents().find('html').html(processedData); }
这种方式的缺点是如果目标页面有动态生成的资源路径,或者特殊的路径规则,可能会漏替换或者替换错误。
思路3:使用代理服务器中转请求
如果目标系统的CORS或认证规则没办法调整,你可以在自己的服务器上搭建一个代理接口:
- 前端请求自己的代理接口,带上认证信息
- 代理接口向后端系统发起请求,添加
Authorization头 - 代理把后端返回的内容(包括HTML和静态资源)转发给前端
- 前端的iframe直接加载代理接口的地址
这样浏览器只会和你的代理服务器交互,不会有跨域问题,认证信息也由代理统一处理,避免了iframe请求无认证的问题。
内容的提问来源于stack exchange,提问作者gbernardes




