跨域访问SCORM API对象遭权限拒绝问题求助
SCORM跨域权限拒绝问题解决方案
问题背景
使用自定义JavaScript函数打开SCORM包时,SCORM尝试访问window.API对象触发权限拒绝错误:Permission denied to access "API" on cross origin object。
现有代码
打开SCORM的核心函数:
openWindow: function (winURL, winName, winW, winH, winOpts) { winOptions = winOpts + ",width=" + winW + ",height=" + winH; newWin = window.open('', winName, winOptions); // Open a new window newWin.moveTo(0, 0); newWin.focus(); const searchParams = new URLSearchParams(window.location.search); //Data for tracking course this.url = window.location.origin; this.base_url = url; this.course_id = searchParams.get('cid'); var response = makeSyncApiCall(this.base_url +"/api/get_course/"+this.course_id, "GET"); if(response.success) { this.path = response.success.scorm_url } else { this.path = ''; } // Check if the URL is provided if (winURL) { // Create an iframe element var iframe = document.createElement('iframe'); iframe.src = this.path +"/"+winURL; iframe.width = '100%'; iframe.height = '100%'; iframe.style.border = 'none'; // Append the iframe to the new window's document body newWin.document.body.appendChild(iframe); return newWin; } },
触发错误的SCORM代码片段:
(((win.API == null) || typeof (win.API) == "undefined") && (win.parent != null) && (win.parent != win))
场景说明:弹窗发起域名与AWS存储的SCORM文件域名不一致,SCORM通过iframe嵌入在新窗口中,尝试向上遍历window.parent访问API对象时被浏览器跨域策略拦截。
核心原因
浏览器同源策略限制:不同域名下的页面无法直接访问彼此window对象的属性,SCORM课程在AWS域名的iframe中,尝试访问父窗口(应用域名)的API对象时,跨域导致权限被拒绝。
解决方案
1. 用postMessage实现跨域通信
- 配置AWS CORS:在SCORM文件所在的AWS存储桶CORS规则中,添加允许应用域名的跨域请求权限,允许
postMessage相关的请求方法和头部。 - 父窗口监听消息:在新打开的弹窗中添加
message事件监听,处理SCORM的API调用请求:newWin.addEventListener('message', function(e) { // 验证消息来源,仅处理SCORM域名的请求 if (e.origin !== 'https://qa-media-xxx.com') return; // 响应SCORM的API获取请求 if (e.data.type === 'requestSCORMAPI') { e.source.postMessage({ type: 'apiResponse', api: window.API }, e.origin); } // 扩展处理其他SCORM方法调用(如SetValue、GetValue等) if (e.data.type === 'scormCall') { const result = window.API[e.data.method](...e.data.args); e.source.postMessage({ type: 'scormResponse', result: result }, e.origin); } }); - 修改SCORM的API查找逻辑:替换原有的
window.parent遍历代码,改用postMessage请求API:function getSCORMAPI() { return new Promise((resolve) => { const messageHandler = function(e) { if (e.data.type === 'apiResponse') { window.removeEventListener('message', messageHandler); resolve(e.data.api); } }; window.addEventListener('message', messageHandler); // 指定父窗口域名,避免全局发送 window.parent.postMessage({ type: 'requestSCORMAPI' }, 'https://your-app-domain.com'); }); } // 调用示例 getSCORMAPI().then(api => { // 执行SCORM操作,如 api.LMSInitialize(''); });
2. 将SCORM部署到应用同域名下
如果业务允许,将AWS存储的SCORM文件迁移到应用域名的子目录或子域名(需配置DNS和反向代理),确保iframe与父窗口同源,这样SCORM可直接访问window.parent.API,无需处理跨域。
3. 配置反向代理统一域名
在应用服务器上配置反向代理,将SCORM文件的请求转发到AWS存储地址,使前端访问SCORM的URL与应用同域名:
- 示例配置:将
https://your-app.com/scorm/*转发到https://qa-media-xxx.com/scorm/* - 修改代码中
iframe.src为反向代理后的路径:this.path = '/scorm';
注意事项
- 使用
postMessage时必须验证消息来源域名,防止恶意请求。 - 反向代理需同步AWS存储的缓存策略,避免资源更新不及时。
- 若无法修改SCORM课程代码,优先选择反向代理或同域名部署方案。
内容的提问来源于stack exchange,提问作者Sheryar Khan
相关产品推荐
相关产品推荐

