Iniezione di iframe in una pagina con criteri di limitazione della sicurezza dei contenuti

Voglio creare un’estensione del browser che crea una barra laterale. Chrome non ha una barra laterale di prima class, quindi dobbiamo invece inserire un iframe nella pagina. Tuttavia, questo si rompe su molte pagine a causa della politica di sicurezza del contenuto. Ad esempio, GitHub utilizza un CSP, che non consente di incorporare iframe di altri siti all’interno di esso. Ad esempio, se provi a inserire il sito web capitalone.com in un iframe su GitHub ottieni quanto segue:

Rifiutato di incorniciare ” https://www.capitalone.com/ ” perché viola la seguente direttiva sulla politica di sicurezza dei contenuti: “frame-src ‘self” render.githubusercontent.com www.youtube.com assets.braintreegateway.com “.

Ecco una semplice estensione per browser per riprodurre questo:

chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) { if (changeInfo.status === 'complete') { chrome.tabs.executeScript(tabId, { code: 'document.body.innerHTML=\'\' + document.body.innerHTML;' }, function() { console.log('Iframe injection complete'); }) } }.bind(this)); 

Tuttavia, secondo Wikipedia, un’estensione del browser dovrebbe essere in grado di iniettare un iframe nonostante qualsiasi politica di sicurezza del contenuto:

Secondo il modello di elaborazione CSP, [20] CSP non dovrebbe interferire con l’operazione dei componenti aggiuntivi del browser o delle estensioni installate dall’utente. Questa funzionalità di CSP consente efficacemente a qualsiasi componente aggiuntivo o estensione di iniettare script in siti Web, indipendentemente dall’origine di tale script, e quindi essere esenti dai criteri CSP.

C’è un altro modo in cui dovrei iniettare un iframe oltre a quello che sto facendo?

L’impossibilità di inserire un iframe esterno in Chrome è un bug ( crbug.com/408932 ).

Se si desidera incorporare una cornice esterna in un sito Web esterno, è necessario caricarla in una cornice che è imballata con la propria estensione.

manifest.json

 { "name": "Embed external site", "version": "1", "manifest_version": 2, "content_scripts": [{ "js": ["contentscript.js"], "matches": ["*://*/*"], "all_frames": true }], "web_accessible_resources": [ "frame.html" ] } 

NON utilizzare chrome.tabs.onUpdated + chrome.tabs.executeScript se si desidera che uno script di contenuto sia sempre inserito in un documento. La tua implementazione è difettosa e può causare lo script per essere eseguito più volte. Invece, dovresti dichiarare lo script di contenuto nel file manifest .

(rimuovere "all_frames": true se non si desidera inserire la cornice in ogni sottoframe.)

contentscript.js

 // Avoid recursive frame insertion... var extensionOrigin = 'chrome-extension://' + chrome.runtime.id; if (!location.ancestorOrigins.contains(extensionOrigin)) { var iframe = document.createElement('iframe'); // Must be declared at web_accessible_resources in manifest.json iframe.src = chrome.runtime.getURL('frame.html'); // Some styles for a fancy sidebar iframe.style.cssText = 'position:fixed;top:0;left:0;display:block;' + 'width:300px;height:100%;z-index:1000;'; document.body.appendChild(iframe); } 

frame.html

  

Displaying https://robwu.nl in a frame

È importante osservare che ho caricato un sito https nel frame. Se si tenta di caricare un sito HTTP nel frame, il criterio del contenuto misto bloccherà il caricamento del frame se uno dei frame principali è una pagina https.

Sostituisci https://robwu.nl/ con http://example.com/ e il riquadro rimarrà vuoto nelle pagine https come https://github.com . Contemporaneamente, il seguente messaggio verrà stampato sulla console.

[blocked] The page at 'https://github.com/' was loaded over HTTPS, but ran insecure content from 'http://example.com/': this content should also be loaded over HTTPS

La risposta di Rob W è corretta. Puoi seguire questo https://transitory.technology/browser-extensions-and-csp-headers/ . Lo faccio funzionare correttamente con la mia estensione per Chrome https://github.com/onmyway133/github-chat

Tieni presente che utilizzo Chrome 59, quindi posso utilizzare la maggior parte delle funzioni di ES6

Dichiara in manifest

 "web_accessible_resources": [ "iframe.html", "scripts/iframe.js" ] 

Crea un iframe nell’evento window.onload

 let url = decodeURIComponent(window.location.search.replace('?url=', '')) let iframe = document.createElement('iframe') iframe.src = url iframe.id = 'github-chat-box-iframe-inner' iframe.style.width = '100%' iframe.style.height = '350px' iframe.style.border = '0px' window.onload = () => { document.body.appendChild(iframe) } 

Il tuo esempio dovrebbe funzionare in Chrome, ma al momento non a causa di un bug: https://code.google.com/p/chromium/issues/detail?id=408932 . La risposta di Rob W contiene una buona soluzione per il problema.