scorm - 简化-scorm window.open(scormUrl)
问题描述
我正在尝试在新窗口中打开我的 SCORM 教育,但是当我这样做时,所有报告都停止工作(如果我在 iframe 中这样做也是如此)。当我只是做 location.href = scormURL; 然后它工作正常。我的 scorm 文件与 LMS 位于不同的域中。
在我的 scorm 响应上执行 loadFromJSON(response) 后,SCORM api 似乎没有被初始化。但是只有当我在新窗口中打开或在 iframe 中显示 scorm 教育时才会出现此问题。
我使用SCORM2004。
编辑:这是 XSS 问题,通过 ocelot 网关路由到 azure CDN 以获取相同的域来解决。
解决方案
我的 scorm 文件与 LMS 位于不同的域中。
这是你的问题。
SCORM 包与您的 LMS(因此也与您的报告)的唯一链接是SCORM API。现代浏览器默认不允许 CORS(跨域资源共享),因为它会使您面临 XSS(跨站点脚本)攻击。
如果外部域中存在 API ,该包可能能够找到该 API,但它无法直接与 LMS 通信。
我解决此问题的方法是在托管 SCORM API 并用于将调用传回 LMS.js
的外部域上添加一个包装文件。Window.postMessage
然后,您可以使用window.open
或您iframe
在外部域上打开一个页面,该页面有权访问scorm_wrapper.js
并拥有iframe
托管您的程序包。
scorm_wrapper.js
因为当当前从不同来源打开时,该Window.opener
方法不可靠且功能不全,我们将直接使用域。window
由于我们控制 LMS,我们知道它正在运行的域,并且由于我们刚刚打开包,我们知道它应该处于活动状态。我们可以postMessage
要求回复。
function receiveMessage(data) {
// We will return to this later...
};
// Be ready for the reply from the LMS.
window.addEventListener('message', receiveMessage(event));
// Ping the domain your LMS is running on.
window.parent.postMessage('ping', 'https://example.com');
postMessage
当我们的 LMS 接收到消息时,它应该用它自己的 a 来回复event.origin
我们的包正在运行的域。
现在,当我们得到 LMS 的回复时,我们就知道我们可以访问了。
var connected = false;
function receiveMessage(data) {
// ...
// Do not do anything unless the message was from
// a domain we trust.
if (event.origin !== 'https://example.com') return;
switch (event.data) {
case 'pong':
connected = true;
break;
// We will return to this later...
}
}
现在,只要从包中调用包装器的 API 对象,我们就可以将消息传递给 LMS。
function sendMessage(args) {
if (!connected) return;
window.parent.postMessage(args, 'https://example.com');
}
const apiWrapper = {
Initialize: function (args) {
sendMessage({ method: 'Initialize', data: args });
},
// More SCORM endpoints...
};
window.API = apiWrapper;
window.API_1484_11 = apiWrapper;
receiveMessage
根据需要添加案例。
function receiveMessage(data) {
// ...
switch (event.data) {
case 'pong':
connected = true;
break;
case 'initialize-acknowledge`:
//...
break;
}
}
这种方法不是很好,但它可以让您安全地解决跨域问题,而无需访问服务器配置。
推荐阅读
- hadoop - 如何有效地更新文件被频繁修改的 Impala 表
- c# - C# WCF GetWebRequest:如何在标头中设置属性
- firebase - 为什么我的 redux 操作没有正确触发?
- java - 是否可以从preparedStatement 获得完整的请求?
- angularjs - Angularjs在单个请求中上传多个文件
- c# - MenuItem 可见性基于子菜单项状态
- machine-learning - 在分类问题中,当类不平衡时,为什么 F1-score 比准确率更合适?
- javascript - 从视频标签中分离控件
- azure-resource-manager - 使用 ARM 模板有条件地添加站点属性
- python - 在google colab中将文件从一个目录复制到另一个目录