Back in 1989, British scientist Tim Berners-Lee invented the World Wide Web. Since then, the world of the Internet has become rich and colorful, and a software named “Web browser” has become popular. Then, cookies, DOM, The Javascript… Browser pages can now interact with each other, so we need a secure way to interact within the browser.
As a solution to this, The Netscape engineers decided to use rules called local domain Policies (SOP) to manage the relationships between these resources…
What is the same origin policy
The same origin policy restricts how documents or scripts loaded from one source can interact with resources from another, an important security mechanism that isolates potentially malicious files and reduces the media that can be attacked.
Definition of homology
If the protocol, port, and host of two urls are the same, the two urls are of the same origin
For example, url -> http://happy.com/home
URL | Whether the same | why |
---|---|---|
http://happy.com/mine |
is | Protocol, port, and host are the same, but the paths are different |
https://happy.com/home |
no | Protocol is different |
http://happy.com:81/home |
no | The port is different |
http://nothappy.com/home |
no | The host is different |
Rules for the same-origin policy
-
Each site has its own resources, such as cookies, DOM, and Javascript namespaces
-
The source of each page comes from its URL (usually schema/protocol, host and port).
-
The script runs in the context of the loaded source. Not where it was loaded from, but where it was finally executed
-
Many resources such as media and graphics are passive resources. They cannot access objects and resources in their loaded context
Based on these rules, we can assume that we have an originA and an originB, and for originA:
- Available from the
originB
Load the script, but can be inoriginB
Used in the context of - The original content and source code of the script cannot be obtained
- Available from the
originB
Load the CSS - Unable to get
originB
The original text of the CSS file in - You can use iframe to access the
originB
Loading the page - Unable to obtain from
originB
Load the IFrame DOM - Available from the
originB
Load the image - Unable to get
originB
The bits of the loaded image - Can play from
originB
In the video - Unable to capture from
originB
Load the image of the video
What happens if there is no same-origin policy
Imagine a scenario where, after logging in to bilibli.com, your user information is stored in Cookie/LocalStorage. At this time, you accidentally visit a phishing site.
The next morning, you open bilibili.com and find that all your money is gone…
Three levels of same-origin policy restrictions
The same origin policy is restricted in DOM, Web data, and network.
The DOM level
Restricts javascript scripts from different sources from reading and writing to the current DOM object, for example 🌰
First, we clicked on the first trending article on the Nuggets front page, and it opened in a new window
And that’s when we found out
The nuggets homepage address is: HTTPS://juejin.cn/The open column address is: HTTPS://juejin.cn/post/6898896417360707591Meets the definition of homologous, that is, the relationship between the two pages is homologousCopy the code
Enter the following code on the column page
The // opener property is a readable and writable property that returns a reference to the Window object that created it
let pdom = opener.document;
pdom.body.style.display = 'none';
Copy the code
We will find the nuggets homepage hidden!!
That is, same-origin pages can manipulate each other’s DOM
Data level
Due to the same origin policy, we cannot access the Cookie, LocalStorage, and IndexDB data of the current source site from sites with different origins
The specific test method is also described above, using the window.opener attribute
The network layer
This restriction refers to the fact that the same origin policy restricts the sending of a site’s data to a site from a different source via, for example, XMLHttpRequest
How to break limits (Across domains)
Data level
Document.domain
Strictly following the same origin policy may cause some problems. For example, if we have two web pages login.example.com and home.example.com, they have the same level 1 domain name, but different level 2 domain name, how can we make them share cookies?
In this case, we can relax the same origin policy a bit and set the same document.domain in both web pages, extending the domain limits to allow all content to extend into the base domain, thereby implementing shared cookies
document.domain = 'example.com';
Copy the code
Points to note:
- This method only applies to Cookie and IFrame Windows. LocalStorage and IndexDB cannot circumvent the same-origin policy by using this method
- The value set by document.domain must be its current field or a parent of its current field
Or specify the domain name of the Cookie by referring to the server
The Set - cookies: key = value; domain=.example.com; path=/Copy the code
The DOM level
Iframe is an HTML inline frame element that allows you to embed other HTML pages in one HTML page
The iframe window and window.open are typical for two different source pages that do not have access to each other’s DOM
An 🌰 :
We insert new.html via iframe in code.html and try to get the DOM node in code.html in new.html
The result, of course… Can’t,
So how to turn the can’t into the can!!
- For some homologous sites, we can adopt
document.cookie
The way of - For sites with completely different sources
window.postmessage
The window.postmessage () method provides a controlled mechanism to circumvent the origin restriction and safely implement cross-source communication
otherWindow.postMessage(message, targetOrigin, [transfer]); Copy the code
For example, 🌰, the parent window communicates with the child iframe:
Parent window to send:
// If the ID of iframe is otherWindow
var iframeWindow = document.getElementById('otherWindow')
// The url is the iframe address
iframeWindow.postMessage('1111', url)
Copy the code
Subifame receives:
window.addEventListener("message".function( event ) {
// The operation you want. }Copy the code
Subiframe sends:
//url is the address of the parent window
window.opener.postMessage('222', url);
Copy the code
The parent window receives messages in the same way as the child iframe receives messages
Canvas pictures
Direct link ~, Zhang Xinxu big guy’s blog
The network layer
JSONP
Jsonp is a “usage mode” of JSON, which can be simply understood as JSON with callback. Jsonp’s idea is to use
// Ideally return data
['a'.'b'];
// Data returned in the real world
callbackFunc(['a'.'b'])
Copy the code
Create a simple JSONp:
function jsonp(req) {
// Dynamically create a script tag
var script = document.createElement('script');
// Create the URL as a concatenation
var url = req.url + '? callback=' + req.callback.name;
script.src = url;
// Add the script tag to the head
document.getElementsByTagName('head') [0].appendChild(script);
}
Copy the code
Method of use
function cb(res) {
console.log(res);
}
jsonp({
url: 'http://XXX.com'.callback: cb
})
Copy the code
Nginx reverse proxy
A nginx reverse proxy is a proxy server that receives requests from the Internet, forwards the requests to an internal server, and returns the response resources from the internal server to the client
Localhost :8080 ->localhost:9090 (localhost:8080 ->localhost:9090)
server {
listen 8080;
server_name localhost;
location / {
proxy_pass http://localhost:9090; # Reverse proxy
add_header Access-Control-Allow-Origin The '*'; # If the current end is cross-domain only without cookies, the value can be *
add_header Access-Control-Allow-Credentials true;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; }}Copy the code
CORS
CORS requires both browser and server support. At present, all browsers support CORS, so it can be said that the key of CORS lies in the server
If CORS is set on the back end, browsers will classify CORS requests into two categories: simple and complex
-
A simple request
A simple request must meet the following conditions
- The request methods are HEAD, GET, and POST
- HTTP header content-type is limited to three values: Application/X-www-form-urlencoded, multipart/form-data, and Text /plain
- No custom HTTP headers (x-Token, etc.) in the request
- None of the XMLHttpRequestUpload objects in the request have any event listeners registered; The XMLHttpRequestUpload object can be accessed using the xmlHttprequest.upload attribute
// For simple requests, the server only needs this setup app.use((req, res) = > { res.setHeader('Access-Control-Allow-Origin'.'xxx')});Copy the code
-
Complex request (cross-domain request with precheck)
For complex requests, an HTTP query request (precheck request), also known as an option request, is added before formal communication to learn whether the server allows cross-domain requests
app.use((req, res, next) = > { res.setHeader('Access-Control-Allow-Origin'.'XXX'); // Allow return headers res.setHeader('Access-Control-Allow-Headers'.'XXX'); // Allow the use of methods res.setHeader('Access-Control-Allow-Methods'.'XXX'); // Precheck the survival time res.setHeader('Access-Control-Max-Age'.6); // If method is OPTIONS, no processing is done if(req.method === "OPTIONS") { res.end(); }});Copy the code
For local development where CORS requests cross domains, you can also use the Google plugin:
Refer to the link
- Developer.mozilla.org/zh-CN/docs/…
- www.netsparker.com/whitepaper-…
- www.w3.org/Security/wi…
- Ruan Yifeng’s browser same origin policy and its circumvention method
- Geek time teacher Li Bing’s browser working principle and practice column
- MDN iframe
- Fragment identifier
- MDN window.postmessage
- Cors look closely