You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

跨域访问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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 23:55:31