在Chrome扩展程序中解决X-Frame-Options DENY问题?

Ian*_*ber 44 javascript iframe google-chrome-extension x-frame-options

我是Intab的作者,是一个Chrome扩展程序,可让您查看内联链接而不是新标签.幕后没有太多花哨的东西,它只是一个加载用户点击的URL的iframe.

除了将X-Frame-Options标头设置为DENY或SAMEORIGIN的网站外,它的效果很好.像谷歌和Facebook这样的一些非常大的网站都使用它,这使得体验略显笨拙.

有没有办法解决这个问题?由于我使用的是Chrome扩展程序,我可以访问哪些浏览器级别的内容可能会有所帮助吗?寻找任何想法或帮助!

Rob*_*b W 62

Chrome提供了webRequest拦截和修改HTTP请求的API.您可以删除X-Frame-Options标题以允许在iframe中内联页面.

chrome.webRequest.onHeadersReceived.addListener(
    function(info) {
        var headers = info.responseHeaders;
        for (var i=headers.length-1; i>=0; --i) {
            var header = headers[i].name.toLowerCase();
            if (header == 'x-frame-options' || header == 'frame-options') {
                headers.splice(i, 1); // Remove header
            }
        }
        return {responseHeaders: headers};
    },
    {
        urls: [ '*://*/*' ], // Pattern to match all http(s) pages
        types: [ 'sub_frame' ]
    },
    ['blocking', 'responseHeaders']
);
Run Code Online (Sandbox Code Playgroud)

在清单中,您需要指定webRequestwebRequestBlocking权限,以及您要拦截的URL模式.

  • 结果是内容脚本无法访问webRequest.我必须把它移到后台. (2认同)
  • @IanMcIntyreSilber你好,我只是想知道你是否曾经有过这个工作,如果你有可能教我. (2认同)
  • @RobW X-Frame-Options可以设置为HTML元元素,请参阅:http://javascript.info/tutorial/clickjacking (2认同)
  • @GuyKorland我明白了.Chrome扩展程序无法修改响应正文,因此您运气不佳. (2认同)
  • @TaiwanGrapefruitTea扩展程序修改的标题不会出现在devtools中.如果您想查看标题修改是否成功,请查看chrome:// net-internals /#events. (2认同)

wOx*_*xOm 28

使用declarativeNetRequest 的ManifestV3 示例

另请参阅此答案末尾的警告!

Chrome 96 及更高版本的 manifest.json
安装过程中不显示“阻止页面内容”的单独权限

  "minimum_chrome_version": "96",
  "permissions": ["declarativeNetRequestWithHostAccess"],
  "host_permissions": ["*://*.example.com/"],
  "background": {"service_worker": "bg.js"},
Run Code Online (Sandbox Code Playgroud)

bg.js 适用于 Chrome 101 及更高版本,使用initiatorDomainsandrequestDomains
(不要忘记"minimum_chrome_version": "101"在 manifest.json 中添加)

const iframeHosts = [
  'example.com',
];
chrome.runtime.onInstalled.addListener(() => {
  const RULE = {
    id: 1,
    condition: {
      initiatorDomains: [chrome.runtime.id],
      requestDomains: iframeHosts,
      resourceTypes: ['sub_frame'],
    },
    action: {
      type: 'modifyHeaders',
      responseHeaders: [
        {header: 'X-Frame-Options', operation: 'remove'},
        {header: 'Frame-Options', operation: 'remove'},
        // Uncomment the following line to suppress `frame-ancestors` error
        // {header: 'Content-Security-Policy', operation: 'remove'},
      ],
    },
  };
  chrome.declarativeNetRequest.updateDynamicRules({
    removeRuleIds: [RULE.id],
    addRules: [RULE],
  });
});
Run Code Online (Sandbox Code Playgroud)

老铬84-100

如果您的扩展应该与这些旧版本兼容,请改用以下内容。

Chrome 84 及更高版本的 manifest.json
安装过程中显示“阻止页面内容”的单独权限

  "permissions": ["declarativeNetRequest"],
  "host_permissions": ["*://*.example.com/"],
  "background": {"service_worker": "bg.js"},
Run Code Online (Sandbox Code Playgroud)

bg.js 适用于 Chrome 84 及更高版本,使用现已弃用的domains

const iframeHosts = [
  'example.com',
];
chrome.runtime.onInstalled.addListener(() => {
  chrome.declarativeNetRequest.updateDynamicRules({
    removeRuleIds: iframeHosts.map((h, i) => i + 1),
    addRules: iframeHosts.map((h, i) => ({
      id: i + 1,
      condition: {
        domains: [chrome.runtime.id],
        urlFilter: `||${h}/`,
        resourceTypes: ['sub_frame'],
      },
      action: {
        type: 'modifyHeaders',
        responseHeaders: [
          {header: 'X-Frame-Options', operation: 'remove'},
          {header: 'Frame-Options', operation: 'remove'},
          // Uncomment the following line to suppress `frame-ancestors` error
          // {header: 'Content-Security-Policy', operation: 'remove'},
        ],
      },
    })),
  });
});
Run Code Online (Sandbox Code Playgroud)

警告:小心站点的服务人员

在添加 iframe 或打开扩展页面之前,您可能必须删除站点的 Service Worker 并清除其缓存,因为许多现代站点使用 Service Worker 来创建页面而不发出网络请求,从而忽略我们的标头 -剥离规则。

  1. 添加"browsingData""permissions"manifest.json中

  2. 清除软件:

    function removeSW(url) {
      return chrome.browsingData.remove({
        origins: [new URL(url).origin],
      }, {
        cacheStorage: true,
        serviceWorkers: true,
      });
    }
    
    Run Code Online (Sandbox Code Playgroud)

    // 如果在 DOM 中添加 iframe 元素:

    async function addIframe(url, parent = document.body) {
      await removeSW(url);
      const el = document.createElement('iframe');
      parent.appendChild(el);
      el.src = url;
      return el;
    }
    
    Run Code Online (Sandbox Code Playgroud)

    // 如果您打开一个扩展页面,<iframe>其 HTML 中包含一个元素:

    async function openPage(url) {
      await removeSW('https://example.com/');
      return chrome.tabs.create({url});
    }
    
    Run Code Online (Sandbox Code Playgroud)