The same-origin policy

An overview,

meaning

The original definition refers to that the cookie set by web page A cannot be accessed by web page B, on the premise that the two web pages must be “homologous”.


“Homology” refers to:

  • The protocols must be the same
  • The domain name must be the same
  • Ports must be the same

purpose

The same-origin policy protects user information from malicious websites

limits

If not homologous, common
Three kinds of behaviorBe restricted:
  • An ajax request
  • Dom not available
  • Cookie, localStorage, and indexDB cannot be read
While these restrictions are reasonable and necessary, sometimes legitimate uses are limited


Second, the Cookie

cookieIs a small piece of information written by the browser that can only be shared by web pages of the same origin. The size limit is 4K.

If the first level domain name of two pages is the same and the second level domain name is different, you can share cookies by setting the same document.domain.

document.domain = "example.com"Copy the code



Note:This method is only suitable for
Cookies and iframe.
localStorage and
indexDB It is not suitable to circumvent the same origin policy in this way
postMessage api.

The server can also set the domain field as a level 1 domain name when setting cookies.

Set-Cookie: key=value; domain=.example.com; path=/Copy the code

What are level 1 and level 2 domain names?




Third, iframe

if
Two pages with different domain namesI can’t get
DOMThe classic example is
iframeWindow and
window.open Open window. They cannot communicate with the parent window.

For example, if the parent window runs the command, an error will be reported if the iframe is not of the same origin.

document.getElementById("myIFrame").contentWindow.document
// Uncaught DOMException: Blocked a frame from accessing a cross-origin frame.Copy the code



contentWindowYes return current
iframeThe object’s
windowObject, which can be passed
windowObject access
iframeInternal documentation and
dom

The reverse is also true if the child window gets the PARENT window’s DOM.

Solutions:

If the level-1 domain name is the same but the level-2 domain name is different, you can set this parameter
document.domain Property, circumvent the same origin policy, get
dom.


If it is
Completely different source pages, there are three ways:
  • Fragment Identifier
  • window.name
  • Cross-document communication API


Fragment Identifier

Fragment identifier, which refers to the hash part of the link URL

For example: “https://www.example.com/blog/2016/04/same-origin-policy.html#name=1” name = 1

Part, only the hash part is changed, the page is not refreshed.

The parent window can write information at the fragment identifier, and the child window listens
hashPartial changes while the page does not refresh.


let src = originUrl + The '#' + data
document.getElementById("myIFrame").src = srcwindow.onhashchange = () => {
    console.log(location.hash)
}Copy the code
Note: The hash part of the URL is marked with #

Similarly, the child window can set the hash portion of the parent window.

parent.location.href = target + The '#' + dataCopy the code


window.name

Window.name refers to the name property of the current window. A window corresponds to a name property, that is, when opened

A new window has nothing to do with the name property of the previous window.

// Set attribute window.name = data // get attribute console.log(document.getelementByid ("myIFrame").contentWindow.name)Copy the code



The advantage of this property is that it can hold longer strings. The disadvantage is that you must listen for the window’s name attribute.


window.poseMessage

Cross-document Messaging API

Allows cross-window communication, regardless of whether the two Windows are homologous

var data = window.open('https://example2.com'.'title')
data.postMessage('hello'.'https://example2.com')Copy the code



The first parameter is the specific content of the message, and the second parameter is the origin of the window that received the message

If yes, https://www.example.com, that is, protocol + domain name + port, can also be set to *



Both parent and child Windows can be listened on
message Event to listen for messages from the other party.

window.addEventListener('message', (e) => {
    console.log(e.data)
})
Copy the code

Arguments to the callback function
e, has three attributes:
  • E.ource: window for sending messages
  • E.olin: Window to receive messages
  • E. data: Message content


LocalStorage

Using window.postMessage, you can also read and write LocalStorage from other Windows.



Four, AJAX

In the same origin policy, requests can only be sent to the SAME URL. There are three ways to avoid the impact of the same Origin policy:
  • JSONP
  • CORS
  • WebSocket


JSONP

The biggest feature is: compatible with the old browser, server transformation is small. Only GET requests can be processed.

The basic ideaIs this:
JSONPThe principle is to use
<script>Tags have no cross-domain limitation vulnerabilities. through
<script>The tag points to an address that needs to be accessed and provides a callback function to receive data. or
<img>The label

Key points:

  • The data returned by the server is notJSON, butJavaScriptThat is to saycontentTypeistext/javascript, the content format iscallbackFunction(JSON)
  • callbackFunctionYou need to registerwindowObject, becausescript The execution scope after loading iswindowscope
  • You need to think about multiple at the same timeJSONPThe condition of the request,callbackFunctionHang onwindowThe attribute name on the
  • End Indicates the request that needs to be removedscriptThe labels andwindowThe callback function on


Usage:

jsonp({
    url: ' ',
    data: {
        key: 'value'
    },
    callback: (data) => {
        console.log(data)
    }
})Copy the code



Implementation method:

functionThe json ({url, data, the callback}) {/ / get the head tag const container = document. The getElementsByTagName ('head') [0]; // Dynamically generates the callback function name const cbName = 'jsonp_${new Date().getTime()}// Create a script tag const dom = document.createElement('script'// Set the SRC attribute of the script tag script.src = '${url}?${objectToQuery(data)}&callback=${cbName}`
    script.type = 'text/javascript'AppendChild (dom) registers the callback function window[cnName] = on windowfunctionContainer.removechild (dom) delete window[cbName]} dom.onError = ()  => { window[cnName] = () => { callback && callback('some error'Container. RemoveChild (dom) delete window[cbName]}}} // Concatenate parametersfunction objectToQuery (obj) { 
    const arr = []; 
    for ( var i in o) { 
        arr.push(encodeURIComponent(i)+ '=' +encodeURIComponent(o[i])); 
    }
    return arr.join('&'); 
}Copy the code



WebSocket

Is a communication protocol that uses ws:// and WSS :// as prefixes because this protocol does not enforce the same origin policy and can communicate across sources as long as the server supports it.

The browser sends a WebSocket request header:


GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
Copy the code

The server determines whether to allow the communication based on the Origin field.


CORS
  • Cross-Origin-ResourceSharingCross-domain resource sharing. The ultimate solution for cross-domain requests.
  • The whole communication process is done automatically by the browser.
  • Once the browser finds outAJAXWhen the request crosses domains, it willAutomatically addSome additional headers, and sometimes an additional request.
  • As long as the server supports itCORS, you can cross domains


Two kinds of requests:

Browsers classify CORS requests into simple requests and non-simple requests

At the same time, the following two conditions are satisfied, is a simple request:
  • The request method is one of the following three:
    • get
    • post
    • head
    • The header information does not exceed the following fields:
      • Accept
      • Accept-Language
      • Content-Language
      • Last-Event-ID
      • Content-type: Only three values: Application/X-www-form-urlencoded, multipart/form-data, text/plain
      Since forms can always be requested across domains, they are compatible with the Content-Type of the form.

      As long as the above conditions are not met, the request is not simple.



      A simple request
      1. The browser detects that the request is simple and automatically adds the Origin field in the header information
      2. Server based onoriginField to determine whether the request is approved or not
        1. To the extent permitted, several headers are added to the response header.
        2. Access-Control-Allow-Origin: http://api.bob.com
          Access-Control-Allow-Credentials: true
          Access-Control-Expose-Headers: FooBar
          Content-Type: text/html; charset=utf-8Copy the code
        3. Not within the permitted range, return a normalHTTPIn response to
        4. The browser determines if there is any in the response headerAccess-Control-Allow-Origin Field, error if no,beXMLHttpRequest onerror Callback function capture. This type of error is not recognized by the status code becauseHTTPThe status code of the response may be200
      Response header field:

      Access-control-allow-origin: This field is required to either be the value of the requested Origin field or * to indicate that Access is allowed by any domain name.

      Access – Control – Allow – Credentials:This field is optional and indicates whether cookies are allowed to be sent. Cookies are not included in cORS requests by default.


      WithCredentials attribute

      CORS requests do not send cookies and HTTP authentication information by default.

      if
      Cookies are sent to the serverOn the one hand, the server agrees to specify
      Access-Control-Allow-CredentialsField.

      Access - Control - Allow - Credentials:trueCopy the code



      On the other hand, it needs to be set in the request
      withCredentialsattribute

      let xhr = new XMLHttpRequest();
      xhr.withCredentials = trueCopy the code



      Note: If you want to send cookies,Access-Control-Allow-OriginThe domain name must be the same as the source of the request.


      Non-simple request

      Common cases: The request method is PUT or DELETE, or the content-type field is Application/JSON.

      1. Non-simple requests are being sentcorsThe request is sent once before it is requestedOPTIONSRequest, calledPrecheck request.
      2. The browser first asks the server if the requested domain name is in the whitelist and what is availableHTTPVerb and header information fields
      3. The browser will only issue a formal response if it receives a positive responseXMLHttpRequesT request


      The fields that will be added to the request header of the precheck request:

      Origin: indicates the request source

      Access-control-request-method: This field is required and represents the Request Method

      Access – Control – Request – Headers:This field represents information about the custom request header


      Response to precheck request
      1. After receiving the precheck request, the server checks the above three fields to confirm that cross-source requests are allowed and responds
      2. If the cross-source request is denied, the server returns a normalHTTPBut there is no correlationCORSThe response header field of. The browser throws an error,beThe XMLHttpRequest onerrorCallback function capture
      3. If a cross-source request is agreed, the server adds some fields to the request header


      Precheck the fields added to the request response header:

      Access-control-allow-methods: GET, POST, PUT. This field is required to represent all requested methods supported by the server

      Access – Control – Allow – Headers:If the request header has
      Access-Control-Request-HeadersField, which must also be present in the response header, representing all header information fields supported by the server

      Access-control-allow-credentials: This field is optional and indicates whether cookies are allowed to be sent. Cookies are not included in cORS requests by default

      Access – Control – Max – Age:This parameter is optional. It indicates the validity period of the precheck request, in seconds. Within the validity period, no other precheck request is sent


      Once the precheck request passes, each subsequent CORS request is treated as a simple request.


      Comparison with JSONP
      • JSONP Only supportgetRequest, but compatible with older browsers
      • CORSAll requests are supported, but not compatibleie10The following
      Reference links:

      Cross-domain resource Sharing CORS
      www.ruanyifeng.com/blog/2016/0…)

      How to achieve a high quality JSONP (
      Juejin. Cn/post / 684490…)

      Browser Same-origin policy and its Circumvention method (
      www.ruanyifeng.com/blog/2016/0…)