javascript 在内容脚本中从模块联合访问remoteEntry

cgvd09ve  于 2023-02-18  发布在  Java
关注(0)|答案(1)|浏览(186)
    • TL; DR**-我可以从chrome扩展的内容脚本中访问模块联合远程吗?

我目前正在开发一个Chrome扩展程序,遇到了如下所示的问题。假设我有两个应用程序-extensionactionsLogger
这些应用程序通过Webpack模块联合链接,如下所示:

    • 操作记录器/网络包. js**
{
  ...,

  plugins: [
    new ModuleFederationPlugin({
      name: 'actionsLogger',
      library: { type: 'var', name: 'actionsLogger' },
      filename: 'remoteEntry.js',
      exposes: {
        './logClick': './actions/logClick',
      }
    }),
  ],

  devServer: {
    port: 3000,
    headers: {
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
      'Access-Control-Allow-Headers': 'X-Requested-With, content-type, Authorization'
    },
    static: {
      directory: path.resolve(__dirname, 'dist'),
    }
  },

  ...
}
    • 扩展名/网络包. js**
{
  ...,
  plugins: [
    new webpack.ProvidePlugin({
      browser: 'webextension-polyfill'
    }),
    new ModuleFederationPlugin({
      name: 'extension',
      remotes: {
        actionsLogger: 'actionsLogger@http://localhost:3000/remoteEntry.js',
      },
    }),
  ],
  ...
}

因此,如您所见,actionsLogger运行在端口3000上,extension通过Module Federation引用它。actionsLogger包含一个简单的函数,用于在发生单击事件时获取光标的位置。

    • 操作记录器/操作/日志单击. js**
function logClick(event) {
  return { X: event.clientX, Y: event.clientY };
}

export default logClick;

其他应用程序-extension,包含chrome扩展的所有代码以及从actionsLogger/logClick导入logClick并在每次点击时将光标位置发送到背景页面的特定脚本:

    • 扩展名/跟踪器. js**
import('actionsLogger/logClick').then((module) => {
  const logClick = module.default;
  
  document.addEventListener("click", (event) => { 
    const click = logClick(event);
    chrome.runtime.sendMessage(click);
  });
});

因此,扩展名中的manifest.json如下所示:

    • 扩展名/清单. json**
{
  ...
  "content_scripts": [{
    "matches": ["<all_urls>"],
    "js": ["tracker.js"]
  }],
  ...
}

问题就来了。如果我试图打开一些安装了扩展并正在运行的网页,我会得到下面的错误:

Uncaught (in promise) ScriptExternalLoadError: Loading script failed.
(missing: http://localhost:3000/remoteEntry.js)
while loading "./logClick" from webpack/container/reference/actionsLogger
    at webpack/container/reference/actionsLogger (remoteEntry.js":1:1)
    at __webpack_require__ (bootstrap:18:1)
    at handleFunction (remotes loading:33:1)
    at remotes loading:52:1
    at Array.forEach (<anonymous>)
    at __webpack_require__.f.remotes (remotes loading:15:1)
    at ensure chunk:6:1
    at Array.reduce (<anonymous>)
    at __webpack_require__.e (ensure chunk:5:1)
    at iframe.js:44:1

首先,我认为我在模块联合设置中配置错了什么,但随后我尝试了以下操作-addedinject. js

    • 扩展/注入. js**
const script = document.createElement('script');
script.src = "chrome-extension://ddgdsaidlksalmcgmphhechlkdlfocmd/tracker.js";
document.body.appendChild(script);

修改了扩展名中的manifest. json

    • 扩展名/清单. json**
{
  ...
  "content_scripts": [{
    "matches": ["<all_urls>"],
    "js": ["inject.js"]
  }],
  "web_accessible_resources": [
    "tracker.js",
  ]
  ...
}

现在Module Federation运行良好,但由于extension/tracker. js从远程导入import('actionsLogger/logClick'),一些定义了内容安全策略的网站可能会阻止此请求(例如IKEA)。
从内容脚本访问MF模块的最初问题可能是因为内容脚本运行在它们自己的隔离环境中,模块联合无法正确解决这个问题。但也许有一些配置标志/选项或一些其他/更好的方法可以使其工作?
会很感激你的建议。

nxagd54h

nxagd54h1#

当然,在我提出这个问题几分钟后,我想到了一个可行的解决方案。所以,基本上,我决定使用第二种方法,即extension/tracker.js通过<script />标记注入到页面上,并且针对CSP问题,我添加了一个实用程序来阻止页面请求上的CSP头。

清单.json

{
  "permissions": [
     ...,
    "webRequest",
    "webRequestBlocking",
    "browsingData",
    ...
  ]
}

扩展名/禁用CSP.js

function disableCSP() {
  chrome.browsingData.remove({}, { serviceWorkers: true }, function () {});

  const onHeaderFilter = { urls: ['*://*/*'], types: ['main_frame', 'sub_frame'] };

  browser.webRequest.onHeadersReceived.addListener(
    onHeadersReceived, onHeaderFilter, ['blocking', 'responseHeaders']
  );
};

function onHeadersReceived(details) {
  for (let i = 0; i < details.responseHeaders.length; i++) {
    if (details.responseHeaders[i].name.toLowerCase() === 'content-security-policy') {
      details.responseHeaders[i].value = '';
    }
  }

  return { responseHeaders: details.responseHeaders };
};

export default disableCSP;

然后在后台脚本中调用disableCSP()
我对这种方法的安全缺陷有点不确定,所以如果这个解决方案引入了潜在的高风险漏洞,请随时告诉我。

相关问题