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:

  1. Available from theoriginBLoad the script, but can be inoriginBUsed in the context of
  2. The original content and source code of the script cannot be obtained
  3. Available from theoriginBLoad the CSS
  4. Unable to getoriginBThe original text of the CSS file in
  5. You can use iframe to access theoriginBLoading the page
  6. Unable to obtain fromoriginBLoad the IFrame DOM
  7. Available from theoriginBLoad the image
  8. Unable to getoriginBThe bits of the loaded image
  9. Can play fromoriginBIn the video
  10. Unable to capture fromoriginBLoad 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 adoptdocument.cookieThe 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

    1. The request methods are HEAD, GET, and POST
    2. HTTP header content-type is limited to three values: Application/X-www-form-urlencoded, multipart/form-data, and Text /plain
    3. No custom HTTP headers (x-Token, etc.) in the request
    4. 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