Cross origin iframe support (#1035)
* Add `recordCrossOriginIframe` setting * Set up messaging between iframes * should emit full snapshot event from iframe as mutation event * this.mirror was dropped on attachIframe * should use unique id for child of iframe * Cross origin iframe recording in `yarn live-stream` * Root iframe check thats supported by firefox * Live stream: Inject script in all frames * Record same origin and cross origin iframes differently * Should map Input events correctly * Turn on other tests * Fix compatibility with newer puppeteer * puppeteer vs 12 seems stable without to many changes needed * normalize port numbers in snapshots * Handle scroll and ViewportResize events in cross origin iframe * Correctly map cross origin mutations * Map selection events for cross origin iframes * Map canvas mutations for cross origin iframes * Update snapshot to include canvas events * Skip all meta events * Support custom events as best we can in cross origin iframes * Use earliest version of puppeteer that works with cross origin live-stream * Map mouse/touch interaction events * Update snapshots for correctly mapped click events * Tweak tests for new puppeteer version * Map MediaInteraction correctly for cross origin iframes * Make tests consistent between high and low dpi devices * Make test less flaky * Make test less flaky * Make test less flaky * Make test less flaky * Add support for styles in cross origin iframes * Map traditional stylesheet mutations on cross origin iframes * Add todo * Add iframe mirror * Get iframe manager to use iframe mirrors internally * Rename `IframeMirror` to `CrossOriginIframeMirror` * Setup basic cross origin canvas webrtc streaming * Clean up removed canvas elements * reset style mirror on new full snapshot * Fix cross origin canvas webrtc streaming * Make emit optional * Run tests on github actions * Upload image artifacts from failed tests * Use newer github actions * Test: hopefully adding more wait will fix it * add extra wait * Fix image snapshot tests * Make tests run with new puppeteer version * upgrade eslint-plugin-jest * Chore: Remove travis ci as ci's running on github actions * Chore: Support recording cross origin iframe in repl * Force developers to update the cross origin iframe mapping when adding new events https://github.com/rrweb-io/rrweb/pull/1035#discussion_r1012516277 * Document cross origin iframe recording * Docs: cross origin iframes recording methods * Docs: AI translated, cross origin iframe recording * rename getParentId to getId * Migrate to @rrweb/types * Run on pull request * doc: improve Chinese doc * Rename `parentId` to `Id` Co-authored-by: Mark-Fenng <f18846188605@gmail.com>
This commit is contained in:
113
docs/recipes/cross-origin-iframes.zh_CN.md
Normal file
113
docs/recipes/cross-origin-iframes.zh_CN.md
Normal file
@@ -0,0 +1,113 @@
|
||||
# 跨域 IFrame 录制
|
||||
|
||||
默认情况下,浏览器很难访问托管在不同域上的 iframe 的内容。 这是一项安全功能,可防止恶意站点访问其他站点上的敏感信息。 rrweb 提供了一个解决方案,但如果您对网站的安全有严格的要求https://stackoverflow.com/a/21629575, 只允许您信任的网站将您的网站嵌入 iframe 中,那我们不建议使用我们的解决方案。
|
||||
因为如果您允许记录跨源 iframe,任何恶意网站都可以嵌入您的网站,并且只要它们运行 rrweb,它们就可以记录您网站的所有内容。
|
||||
|
||||
## 如何记录跨源 iframe
|
||||
|
||||
在父页面中启用录制跨域 iframe:
|
||||
|
||||
```js
|
||||
rrweb.record({
|
||||
emit(event) {}, // 所有事件都将在此处发出,包括来自跨源 iframe 的事件
|
||||
recordCrossOriginIframes: true,
|
||||
});
|
||||
```
|
||||
|
||||
在您的子页面中启用重放跨域 iframe:
|
||||
|
||||
```js
|
||||
rrweb.record({
|
||||
emit(event) {}, // 这是 rrweb 所必需的,但子页面不会发出任何事件
|
||||
recordCrossOriginIframes: true,
|
||||
});
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
当跨源 iframe 录制开启时,rrweb 将检查它是否正在顶级窗口中运行。 如果不是,它将通过 `postMessage` 将事件发送到父窗口。
|
||||
|
||||
如果您没有在顶层窗口中运行 rrweb,则打开 `recordCrossOriginIframes` 时事件将丢失。
|
||||
|
||||
如果顶层窗口是一个恶意网站,它可以监听事件并将它们发送到它选择的服务器。或者如果您的页面上正在运行恶意脚本,则它们可以监听“postMessage”,又因为子窗口和父窗口之间的通信未加密,所以他们可以获取到所有事件。
|
||||
|
||||
## 将 rrweb 注入跨源 iframe 的选项
|
||||
|
||||
### 1. 网站所有者,在 iframe 中添加 rrweb
|
||||
|
||||
如果您拥有使用 iframe 的网站和嵌入在 iframe 中的网站,您可以通过脚本标签将 rrweb 添加到这两个页面。
|
||||
|
||||
### 2. 浏览器扩展
|
||||
|
||||
请查看 https://developer.chrome.com/docs/extensions/mv3/content_scripts/#functionality
|
||||
|
||||
### 3. Puppeteer script
|
||||
|
||||
```js
|
||||
import puppeteer from 'puppeteer';
|
||||
|
||||
async function injectRecording(frame) {
|
||||
await frame.evaluate((rrwebCode) => {
|
||||
if (window.__IS_RECORDING__) return;
|
||||
window.__IS_RECORDING__ = true;
|
||||
|
||||
(async () => {
|
||||
function loadScript(code) {
|
||||
const s = document.createElement('script');
|
||||
s.type = 'text/javascript';
|
||||
s.innerHTML = code;
|
||||
if (document.head) {
|
||||
document.head.append(s);
|
||||
} else {
|
||||
requestAnimationFrame(() => {
|
||||
document.head.append(s);
|
||||
});
|
||||
}
|
||||
}
|
||||
loadScript(rrwebCode);
|
||||
|
||||
window.rrweb.record({
|
||||
emit: (event) => {
|
||||
window._captureEvent(event);
|
||||
},
|
||||
recordCrossOriginIframes: true,
|
||||
});
|
||||
})();
|
||||
}, code);
|
||||
}
|
||||
|
||||
const browser = await puppeteer.launch();
|
||||
const page = (await browser.pages())[0];
|
||||
|
||||
const events = []; // 包含来自所有Frame的所有事件
|
||||
|
||||
await page.exposeFunction('_captureEvent', (event) => {
|
||||
events.push(event);
|
||||
});
|
||||
|
||||
page.on('framenavigated', async (frame) => {
|
||||
await injectRecording(frame); // 将 rrweb 注入 iframe
|
||||
});
|
||||
|
||||
await page.goto('https://example.com');
|
||||
|
||||
// 您的事件将在事件数组中
|
||||
```
|
||||
|
||||
### 4. Electron
|
||||
|
||||
```ts
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'rrweb-recording-script.js'),
|
||||
// 这会打开 iframe 内的预加载,但会禁用节点集成
|
||||
nodeIntegrationInSubFrames: true,
|
||||
nodeIntegration: false,
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
请查看 https://www.electronjs.org/docs/latest/tutorial/tutorial-preload
|
||||
和 https://www.electronjs.org/docs/latest/tutorial/process-model#preload-scripts
|
||||
Reference in New Issue
Block a user