One, foreword
In the demand iteration before Mid-Autumn Festival, I encountered A problem of iframe cross-domain communication. The field in an interface request of domain name B used the account ID under domain name A. The original code directly used sessionstorage.getitem (info) to obtain user information from the cache of domain name A, but the result was not obtained.
So I started thinking about iframe in my head and realized that information under different domains is not directly available. Yes, this should be familiar with the basics of iframe, I rely on a few minutes of recall to remember. After changing the requirements, I thought it was time for me to revisit my knowledge of iframe.
The following introduction to IFrame is mainly from MDN.
2. Basic information
Three, attributes,
3.1 allow
User indicates the signature policy.
3.1.1 Feature Policy
A brief introduction to feature policies, which allow Web developers to enable, disable, and modify the behavior of exact features and apis in the browser. Content security policies, for example, control the browser’s characteristically insecure behavior. Allow is an iframe specific feature policy that controls which features an IFrame uses.
Syntax for characteristic policies
<allowlist>
Copy the code
*: This feature is allowed by default in the top layer and included content (iframes).
‘self’: This feature is allowed by default at the top level, while contained content (iframes) uses the same Settings as the source address. That is, this feature does not allow cross-domain access in iframe.
‘None ‘: This feature is disabled by default both at the top level and in contained content (iframes).
‘SRC ‘: (allowed in iframe only) This feature is allowed in iframe as long as the URL in SRC is the same URL used to load the iframe.
Where * or ‘none’ is allowed alone, while ‘self’ and ‘SRC’ can be used with multiple source addresses.
3.1.2 grammar
Disable the full-screen mode
You can set fullscreen’s signature policy to ‘None’.
<iframe allow="fullscreen 'none'">
Copy the code
Multiple signature policies are supported
Disable the full-screen mode and disable the call up payment interface, separated by a semicolon.
<iframe allow="fullscreen 'none'; payment 'none'">
Copy the code
3.2 a CSP
Configure content security policies for embedded resources.
Content Security Policy (CSP)
Content Security Policies (CSP) are an additional layer of security to detect and weaken certain types of attacks, including cross-site scripting (XSS (EN-US)) and data injection attacks. Whether it is data theft, website content contamination or the distribution of malicious software, these attacks are the main means.
Set content security policies
For example, an imported CSS file, if we set the following policy, prohibits the loading of any resources except the stylesheet from cdn.example.com.
Set security policy in head and import external CSS file:
<! DOCTYPE html><html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="Width = device - width, initial - scale = 1.0" />
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'cdn.example.com'; " />
<title>iframe-child</title>
<link rel="stylesheet" href="./style.css" />
</head>
<body>.</body>
</html>
Copy the code
If you open the page in the browser and open the developer tool, you can see an error:
Refused to load the stylesheet 'file:///Users/Desktop/weblearn/iframe/style.css' because it violates the following Content Security Policy directive: "style-src 'cdn.example.com'". Note that 'style-src-elem' was not explicitly set, so 'style-src' is used as a fallback.
Copy the code
This means that the stylesheet is only allowed to load from CDn.example.com, whereas the page attempted to load from its own source (example.com).
3.3 height
Specify the height of the frame in CSS pixel format HTML5, or pixel format HTML 4.01, or percentage format. The default value is 150.
3.4 importance
Represents the load priority of the resource specified by the SRC attribute of
Auto (default) : no priority is specified. The browser determines the load order of resources based on its own situation
“High” : The resource loading priority is high
Low: The loading priority of resources is low
3.4 the name
The name used to locate the embedded browsing context. This name can be used as the target value of the < A > and
Used as the target attribute value for the tag
<iframe name="myIframe" src="http://www.w3cschool.cc" width="500" height="200"></iframe>
<a href="https://juejin.cn/" target="myIframe">The Denver nuggets</a>
Copy the code
Display before clicking the gold digging button:
Click the gold digging button to display:
Open the page in the Iframe window
Use window.open() to open the window. The second argument to this method specifies the window name. We use window.name to get the name of the iframe and assign it to window.open().
The parent page:
<iframe name="myIframe" src="./child.html" width="500" height="200"></iframe>
Copy the code
The iframe page
<! DOCTYPE html><html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="Width = device - width, initial - scale = 1.0" />
<title>iframe-child</title>
</head>
<body>
<div>
<input type="button" id="open" value="Pop over" />
</div>
<script>
window.onload = function () {
var div = document.querySelector('div');
document.querySelector('#open').onclick = function () {
window.open('https://juejin.cn/'.window.name);
};
};
</script>
</body>
</html>
Copy the code
You can open the nuggets page in the current IFrame window:
3.5 referrerpolicy
Represents how to send the referrer header when obtaining an iframe resource:
No-referrer: do not send the Referer header.
No-referreer-when (default): the Referer header will not be sent when sending a request to an origin that is not protected by TLS (HTTPS).
Origin: The source that contains only the source page in the referrer header. In other words, just the scheme, host, and port (en-us) of the source page.
Origin-when -cross-origin: When a cross-domain request is made, only the source of the source page is included in the referrer. When a same-origin request is made, the referrer still contains the path information of the source page on the server.
Same-origin: For same Origin requests, the referrer header is sent. Otherwise, the referrer header is not sent.
Strict-origin: The referrer header is sent only if the requested page and the source page have the same protocol security level (for example, requesting an HTTPS page from another HTTPS page). If the requested page has a low protocol security level, the referrer header will not be sent (such as requesting an HTTP page from an HTTPS page).
Strict-origin-when -cross-origin: Contains the full URL in the referrer header when an origin request is initiated. When the requested page and the source page have different sources but the same protocol security level (e.g. HTTPS→HTTPS), only the source of the source page is included in the referrer header. When the protocol security level of the requested page is low (e.g. HTTPS→HTTP), the referrer header is not sent.
Unsafe-url: Always contains the source and path (but not the fragment, password, or user name) in the header of the referrer. This value is not secure because doing so exposes source and path information for TLS protected resources.
Don’t add referrerpolicy
<iframe name="myIframe" src="https://juejin.cn/" width="500" height="200" />
Copy the code
The source of the referrer can be seen in the request:
no-referrer
Set the value of referrerPolicy to no-referrer
<iframe name="myIframe" src="https://juejin.cn/" width="500" height="200" referrerpolicy="no-referrer" />
Copy the code
We don’t see the source of the referrer in the request:
origin
Set the referrerPolicy value to Origin
<iframe name="myIframe" src="https://juejin.cn/" width="500" height="200" referrerpolicy="origin" />
Copy the code
The source of the referrer can be seen in the request:
origin-when-cross-origin
Set the referrerPolicy value to origin-time-cross-origin
<iframe name="myIframe" src="https://juejin.cn/" width="500" height="200" referrerpolicy="origin-when-cross-origin" />
Copy the code
Source of referrer for non-source requests:
same-origin
Set the referrerPolicy value to SAME-Origin
<iframe name="myIframe" src="https://juejin.cn/" width="500" height="200" referrerpolicy="same-origin" />
Copy the code
Referrer cannot be seen for non-source requests:
<iframe name="myIframe" src="http://localhost:8888/test/iframe" width="500" height="200" referrerpolicy="same-origin" />
Copy the code
The source of the referrer can be seen:
strict-origin-when-cross-origin
Set the referrerPolicy value to strict-origin-when-cross-origin
<iframe name="myIframe" src="http://localhost:8888/test/iframe" width="500" height="200" referrerpolicy="strict-origin-when-cross-origin" />
Copy the code
For same-origin requests, you can see the full path in the referrer’s source:
unsafe-url
Set the referrerPolicy value to unsafe-URL
<iframe name="myIframe" src="https://juejin.cn/" width="500" height="200" referrerpolicy="unsafe-url" />
Copy the code
The source of the referrer and the complete path can be seen in the source of the referrer:
3.6 the sandbox
This property enables some additional restrictions on what is rendered in the IFrame framework. The property value can be an empty string, in which case all restrictions are enabled, or a specified series of strings separated by Spaces. Valid values are:
Allow-downloads-without-user-activation: Allows files to be downloaded without the user’s consent.
Allow-forms: Allows embedded browsing contexts to submit forms. If this keyword is not used, the form cannot be submitted.
Allow-modals: Allows embedded browsing context to open modal Windows.
Allow-orientation -lock: Allows embedded browsing context to lock the screen orientation (e.g. horizontal or vertical orientation on smartphones and tablets).
Allow-pointer-lock: Allows embedded browsing contexts to use the Pointer Lock API.
Allow-popups: allows pop-ups (for example, windod. open, target=”_blank”, showModalDialog). If this keyword is not used, the corresponding function is automatically disabled.
Allow-popups-to-escape-sandbox: Allows a sandboxed document to open a new window, and the new window does not inherit the sandbox flag. For example, safely sandbox an AD page without enabling the same restrictions on a new page to which the AD links.
Allow-presentation: Allows the embedded browsing context to start a presentation session.
Allow-same-origin: If this keyword is not used, the embedded browsing context will be treated as coming from an independent source, which will make same-Origin policy same-Origin check fail.
Allow-scripts: Allows embedded browsing context to run scripts (but not to create popovers). If you do not use this keyword, you cannot run the script.
Allow-storage-access-by-user-activation: Allows the embedded browsing context to use the storage capabilities of the parent browsing context through the Storage Access API.
Allow-top-navigation: Allows embedded browsing context to navigate (load) content into top-level browsing context.
Allow-top-navigation -by-user-activation: Allows the embedded browsing context to navigate (load) content to the top-level browsing context with the user’s permission.
3.7 the SRC
The URL of the nested page. Use the about:blank value to embed a blank page that complies with the same origin policy. Using code in Firefox (Version 65 and later), Chromium-based browsers, Safari/iOS to remove the SRC attribute of an iframe (e.g. via element.removeAttribute ()) can cause About: Blank is loaded into frame.
<iframe name="myIframe" src="https://juejin.cn/" width="500" height="200"></iframe>
Copy the code
The iframe window displays the gold digging page set by SRC:
3.8 srcdoc HTML 5 only
This property is a piece of HTML code that is rendered into the iframe. If the browser does not support the SRCdoc attribute, the content represented by the SRC attribute is rendered.
3.9 width
Specify the width of the frame in CSS pixel format HTML5, or in pixel format HTML 4.01, or in percentage format. The default value is 300.
Four, scripts,
Inline frames, like the element, are contained in the window.frames pseudo-array (an array-like object).
With the DOM HTMLIFrameElement object, scripts can access the window object of the inline frame via contentWindow. The contentDocument attribute references the document element inside
Inside the framework, scripts can refer to parent window objects via window.parent.
Script access to framework content must comply with the same-origin policy and cannot access almost all properties of non-same-origin Window objects. The same origin policy also applies to the child form accessing the parent form’s Window object. Cross-domain communication can be implemented through window.postMessage.
4.1 The script accesses the window object of the inline frame through contentWindow
Inline iframe pages, you can use scripts to access the window object of the inline frame via contentWindow and change the style of the inline frame, such as changing the background color and font color of the inline frame in the following code example:
iframe.html
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="Width = device - width, initial - scale = 1.0" />
<title>iframe</title>
<link rel="stylesheet" href="./index.css" />
</head>
<body>
<div class="wrap">
<div class="mb20 font-lg">Iframe</div>
<input type="button" class="mb20" onclick="changeStyle()" value="Modify background color" />
<! -- Local page will report same origin error -->
<iframe id="myIframe" src="http://127.0.0.1:3000/child/" width="500" height="200"></iframe>
</div>
</body>
<script>
function changeStyle() {
var x = document.getElementById('myIframe');
var y = x.contentWindow || x.contentDocument;
if (y.document) y = y.document;
y.body.style.backgroundColor = '#d80000';
y.body.style.color = '#fff';
}
</script>
</html>
Copy the code
child.html
<! DOCTYPE html><html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="Width = device - width, initial - scale = 1.0" />
<title>iframe-child</title>
</head>
<body>
<div>Change the background color</div>
</body>
</html>
Copy the code
UI
Note: An error will be reported if you change the properties of an inline frame using contentWindow if you open a local page directly in Chrome:
DOMException: Blocked a frame with origin "null" from accessing a cross-origin frame.
Copy the code
After searching baidu, I learned that this problem was caused by Chrome’s same-origin policy and only occurred when the page was loaded with scripts, so I used Node to start a simple Web server and then accessed the page functions through the local service. Post my Node.js code:
/ / target:
/ / the browser type http://127.0.0.1:3000/iframe/, shows the iframe. HTML
1. Load the Express module
const express = require('express');
2. Create a server
const app = express();
3. Start the server
app.listen(3000.() = > {
console.log('express-server is running... ');
});
const path = require('path');
// 4. Listen for routes
app.get('/iframe'.(req, res) = > {
res.sendFile(path.join(__dirname, 'view'.'iframe.html'), err= > {});
});
app.get('/child'.(req, res) = > {
res.sendFile(path.join(__dirname, 'view'.'child.html'), err= > {});
});
Copy the code
The browser type http://127.0.0.1:3000/iframe/ to access to the local page:
4.2 Framework internal scripts can access parent window objects through window.parent
Frame internal scripts can change the style of the parent window by accessing the parent window object via window.parent
iframe.html
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="Width = device - width, initial - scale = 1.0" />
<title>iframe</title>
<link rel="stylesheet" href="./index.css" />
</head>
<body>
<div class="wrap">
<div class="mb20 font-lg">Iframe</div>
<div class="box" id="box">The parent page box</div>
<! -- Local page will report same origin error -->
<iframe id="myIframe" src="http://127.0.0.1:3000/child/" width="500" height="200"></iframe>
</div>
</body>
</html>
Copy the code
child.html
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="Width = device - width, initial - scale = 1.0" />
<title>iframe-child</title>
</head>
<body>
<div>
<input type="button" id="changeColor" value="Change the parent page color" />
</div>
<script>
window.onload = function () {
var div = document.querySelector('div');
document.querySelector('#changeColor').onclick = function () {
var parent = window.parent.document.getElementById('box');
parent.style.backgroundColor = '#d80000';
parent.style.color = '#fff';
};
};
</script>
</body>
</html>
Copy the code
UI
Five, positioning and scaling
As an alternative element, you can use Object-position and object-Fit to locate, align, and scale documents within the element.
Iframe cross-domain communication
The basic knowledge of IFrame has been reviewed in front of it to deepen the understanding of IFrame. So the problem we encountered in the actual business requirements at the beginning, iframe cross-domain communication comes up.
Before we talk about cross-domain communication, let’s look at what cross-domain is and what the common cross-domain scenarios are.
6.1 cross domain
6.1.1 Same-origin Policy
The same origin policy is an important security policy that restricts how an Origin document or the scripts it loads can interact with resources from another source. It can help block malicious documents and reduce the number of vectors that can be attacked.
If the protocol, host, and port tuple of two urls are the same, the two urls are cognate.
If either protocol, host, or port tuple of two urls is different, the two urls from different sources request resources from each other, which is called cross-domain communication.
6.1.2 Cross-domain Scenario
The table below gives the with URL store.company.com/dir/page.ht… Examples of sources for comparison:
URL | The results of | why |
---|---|---|
Store.company.com/dir2/other…. | homologous | Only the path is different |
Store.company.com/dir/inner/a… | homologous | Only the path is different |
store.company.com/secure.html | failure | Agreement is different |
Store.company.com: 81 / dir/etc. HTM… | failure | Different ports (http://default port is 80) |
News.company.com/dir/other.h… | failure | The host different |
6.2 Iframe Cross-domain Communication Solution
We call the page embedded with iframe as the parent page, and the nested page as the child page. Data needs to be transferred between the two pages to achieve the functions we need. Communication in different directions is also implemented in different ways.
6.2.1 The parent page passes data to the child pages
1. Use the SRC element of the iframe tag
SRC is the URL address of the nested page. Parameters can be added after the URL address. The nested page can obtain the current URL address through window.location.href to obtain the parameters carried in the URL address. Such as:
iframe.html
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="Width = device - width, initial - scale = 1.0" />
<title>iframe</title>
<link rel="stylesheet" href="./index.css" />
</head>
<body>
<div class="wrap">
<div class="mb20 font-lg">Iframe</div>
<iframe id="myIframe" src="./child.html? accountId=10"></iframe>
</div>
</body>
</html>
Copy the code
child.html
<! DOCTYPE html><html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="Width = device - width, initial - scale = 1.0" />
<title>iframe-child</title>
</head>
<body>
<div id="child"></div>
<script>
window.onload = function () {
var div = document.querySelector('div');
const params = window.location.href.split('? ');
const accountId = params[1].split('=') [1];
var node = document.createElement('div');
node.innerHTML = The current account ID is${accountId}`;
div.appendChild(node);
};
</script>
</body>
</html>
Copy the code
UI
2.postMessage
Let’s take a quick look at what postMessage does, from MDN.
The window.postMessage() method can safely implement cross-source communication.
grammar
otherWindow.postMessage(message, targetOrigin, [transfer]);
Copy the code
otherWindow
A reference to another window, such as the contentWindow property of iframe, the window object returned by executing window.open, or the window.frames named or numeric index.
message
Data to be sent to other Windows. It will be serialized by a structured cloning algorithm. This means you can safely pass data objects to the target window without having to serialize them yourself. [1]
targetOrigin
The origin property of a window specifies which window can receive message events. The value can be a string “” (for unrestricted) or a URI. If any of the protocol, host address, or port of the target window does not match the value provided by targetOrigin, the message will not be sent. A message will only be sent if all three match. This mechanism controls which Windows messages can be sent to; For example, this parameter is especially important when a password is sent using postMessage, and its value must be exactly the same as the Origin property of the intended recipient of the message containing the password to prevent the password from being intercepted by a malicious third party. If you know exactly which window the message should be sent to, always provide a targetOrigin with an exact value instead of. Not providing an exact target will result in data being leaked to any malicious site interested in the data.
Transfer the optional
Is a string of Transferable objects that are passed along with Message. Ownership of these objects is transferred to the receiver of the message, and ownership is no longer retained by the sender.
iframe.html
The parent page communicates to the child page via postMessage, with targetOrigin set to ‘*’ and no origin restriction.
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="Width = device - width, initial - scale = 1.0" />
<title>iframe</title>
</head>
<body>
<div class="wrap">
<div class="mb20 font-lg">Iframe</div>
<iframe id="myIframe" src="http://127.0.0.1:3002/child/"></iframe>
</div>
</body>
<script>
const myIframe = document.getElementById('myIframe');
myIframe.onload = function () {
myIframe.contentWindow.postMessage('father page sent messages: child pages url to http://127.0.0.1:3002/child/'.The '*');
};
</script>
</html>
Copy the code
child.html
The child page listens for the parent page message event using window.addEventListener, and the callback event can fetch the data passed by the parent page from event.data.
<! DOCTYPE html><html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="Width = device - width, initial - scale = 1.0" />
<title>iframe-child</title>
</head>
<body>
<div id="child">
<div style="margin-bottom: 10px;">Sub-page display:</div>
</div>
<script>
// Listen for the parent page message event
window.addEventListener('message', receive, false);
// The callback function
function receive(event) {
// The passed data can be obtained from event.data
var div = document.querySelector('div');
var node = document.createElement('div');
node.innerHTML = event.data;
div.appendChild(node);
}
</script>
</body>
</html>
Copy the code
UI
6.2.2 Child pages pass data to parent pages
The child page can also pass data to the parent page via postMessage, except that otherWindow is the parent page window, so the child page needs to use window.parent to represent the parent page window (see 4.2).
child.html
Child pages communicate to parent pages via postMessage, with targetOrigin set to ‘*’ without origin restriction.
<! DOCTYPE html><html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="Width = device - width, initial - scale = 1.0" />
<title>iframe-child</title>
</head>
<body>
<div id="child"></div>
<script>
window.parent.postMessage('the child pages sent messages: the parent page url to http://127.0.0.1:3000/iframe/'.The '*');
</script>
</body>
</html>
Copy the code
iframe.html
The parent page uses window.addEventListener to listen for child page message events, and the callback event can fetch the data passed by the child page from event.data.
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="Width = device - width, initial - scale = 1.0" />
<title>iframe</title>
</head>
<body>
<div class="wrap">
<div class="mb20 font-lg">Iframe</div>
<div id="box">Parent page display:</div>
<br />
<iframe id="myIframe" src="http://127.0.0.1:3002/child/"></iframe>
</div>
</body>
<script>
// Listen for child page message events
window.addEventListener('message', receive, false);
// The callback function
function receive(event) {
// The passed data can be obtained from event.data
var div = document.getElementById('box');
var node = document.createElement('div');
node.innerHTML = event.data;
div.appendChild(node);
}
</script>
</html>
Copy the code
UI
Seven,
Review the old and learn the new, can be a teacher. The ancients did not deceive me.
By learning iframe again, I gained a deeper understanding of IFrame and a deeper memory of cross-domain solutions that I often didn’t remember well before.
Time does not wait for me. Thank you for your persistence. Come on!