This is the fourth day of my participation in the August More text Challenge. For details, see:August is more challenging

Cross domain, a nagging question of interaction is front end must also often encounter problems, believe everyone not unfamiliar, though not something profound, but scaffold layers of packaging, all kinds of API emerge in endlessly, is some overwhelmed, so this kind of situation, only oneself to summarize, if it is not so familiar to you, I’m sure it will help you

One of the first concepts to understand before talking about cross-domain is the same origin policy

Because of browser security policy restrictions, addresses of different sources cannot access resources or manipulate the DOM

If you don’t know about the same origin policy, see my other article: Understanding Browser security (same origin restriction /XSS/CSRF/ Man-in-the-middle attack).

What are the cross-domain solutions?

Here is only a few development used in the more, almost not to use such as:

  • Document. domain + iframe: applies to cross-domain scenarios where the primary domain name is the same but the sub-domain name is different
  • Window. name + iframe: the value of name can be up to 2M, and the features still exist after loading different pages or domain names
  • Location. hash + iframe: Applies to the scenario where page A communicates with page B through page C

I’m not going to expand it too much

1. CORS

That’s a popular interview question

CORS communication process is automatically completed by the browser, the browser (support) and server support, so the key is as long as the server support, you can cross domain communication, CORS request is divided into two categories, simple request and non-simple request

In addition, CORS requests do not contain cookies or HTTP authentication information by default. If cookies are required, several conditions must be met:

  • The server specifiesAccess-Control-Allow-Credentials: true
  • The developer must enable the withCredentials property in the request:xhr.withCredentials = true
  • Access-control-allow-origin is not an asterisk, specify an explicit domain name that matches the requested web page, so that cookies from other domains are not uploaded

A simple request

A simple request requires two conditions to be met:

  • The request method is:HEAD,GET,POSTOne of the three
  • Request header information should not exceed the following fields:
    • Accept
    • Accept-Language
    • Content-Language
    • Last-Event-Id
    • Content-type: One of the three values: Application/X-www /form/urlencoded, multipart/form-data, text/plain

These conditions are needed for form compatibility, because forms have historically been able to cross domains

The browser directly sends the CORS request. Specifically, the Origin field is added to the header information to indicate which domain (protocol + domain name + port) the request comes from. The server decides whether to approve the request according to this value. If yes, the response will be returned with more than the following response headers

Access-Control-Allow-Origin: http:// This field is required to be consistent with Orign
Access-Control-Allow-Credentials: true // The field indicating whether cookies are allowed is optional
Access-Control-Expose-Headers: FooBar // This field is optional
Content-Type: text/html; charset=utf-8 // Represents the document type
Copy the code

The server needs to set at least the access-control-allow-Origin field in a simple request

Non-simple request

For example, a PUT or DELETE request, or a content-type of application/ JSON, is a non-simple request.

This is not a simple CORS request. Before a formal request, an options-type query request, called a precheck request, is sent to ask whether the server supports the request of the domain name where the web page resides and which header fields can be used. A formal XMLHttpRequest request is made only when a positive response is received, otherwise an error is reported

The method for prechecking a request is OPTIONS, which has several fields in its header

  • Origin: Indicates the field from which the request came. This field is required
  • Access-control-request-method: Lists which HTTP methods are used for CORS requests. This field is required
  • Access-control-request-headers: Specifies the additional header fields to be sent for CORS requests, separated by commas (,)

Too many OPTIONS requests can also cost performance, so to minimize OPTIONS requests, you can ask the server to add them in the request return header

Access-Control-Max-Age: Number // The number is in seconds
Copy the code

Indicates how long the return result of a precheck request can be cached, within which time no precheck is required for further requests. But this cache only works for the exact same URL

2. Nginx agent cross-domain

Configure a proxy server to request to the server, and then return the data to the client, the essence and CORS cross-domain principle is the same, need to configure the request response header access-control-allow-Origin and other fields, forward proxy and reverse proxy see my another HTTP article has the introduction

server { 
    listen 81; server_name www.domain1.com; 
    location / { 
        proxy_pass http://xxxx1:8080; // Reverse proxy
        proxy_cookie_domain www.xxxx1.com www.xxxx2.com; // Modify the domain name in cookie
        index index.html index.htm; 
        // When using middleware proxy interfaces such as Webpack-dev-server to access Nignx, no browser is involved, so there is no same-origin restriction. The following cross-domain configuration is not enabled
        add_header Access-Control-Allow-Origin http://www.xxxx2.com; // If the current end only crosses domains and does not contain cookies, the value can be *
        add_header Access-Control-Allow-Credentials true; }}Copy the code

3. Node middleware proxy is cross-domain

Config.js in Vue

module.export = {
    ...
    devServer: {
        proxy: {
            [ process.env.VUE_APP_BASE_API ]: {
                target: 'http://xxxx'.// Proxy cross-domain target interface
                ws: true.changeOrigin: true.pathRewrite: {[A '^' + process.env.VUE_APP_BASE_API ] : ' '
                }
            }
        }
    }
}
Copy the code

Node + express

const express = require('express')
const proxy = require('http-proxy-middleware')
const app = express()
app.use('/', proxy({ 
    // Proxy cross-domain target interface
    target: 'http://xxxx:8080'.changeOrigin: true.// Modify the response header to cross domains and allow cookies
    onProxyRes: function(proxyRes, req, res) { 
        res.header('Access-Control-Allow-Origin'.'http://xxxx')
        res.header('Access-Control-Allow-Credentials'.'true')},// Modify the cookie domain name in the response information
    cookieDomainRewrite: 'www.domain1.com' // The value can be false, indicating no modification
})); 
app.listen(3000); 
Copy the code

4. WebSocket

WebSocket is a communication protocol in the HTML5 standard, ws://(non-encryption) and WSS ://(encryption) as the protocol prefix, the protocol does not implement the same-origin policy, as long as the server supports the line

The WebSocket request header contains the Origin field, which indicates the domain from which the request source comes. The server can determine whether to allow the communication based on this field. If the request is in the whitelist, the communication can be allowed

// Use the socket. IO plugin
<script src="https://cdn.bootcss.com/socket.io/2.2.0/socket.io.js"></script> 
<script> 
    const socket = io('http://xxxx:8080'); // The connection was processed successfully
    socket.on('connect'.function() { 
        // Listen for server messages
        socket.on('message'.function(msg) { 
            console.log('New message' + msg); 
        }); 
        // The listener server is closed
        socket.on('disconnect'.function() { 
            console.log('Connection closed'); })})</script>
Copy the code

5. postMessage

PostMessage is an API in the HTML5 standard that solves the following problems:

  • Data transfer between the page and the newly opened window
  • Data transfer between multiple Windows
  • Data is passed between the page and the nested iframe
  • Between the three scenes aboveCross domain transfer

PostMessage takes two arguments and uses them as follows:

  • Parameter 1: data to be sent
  • Parameters of the two: Write down the address of the person you want to send it toProtocol + domain name + port), can also be set to*, represents any window, is/Represents a window that is the same source as the current window
/ / the sender
window.parent.pastMessage('Sent data'.'http://received address') 
Copy the code

If it is sent to an iframe

/ / the sender
<iframe id="iframe" src="http://xxxx"></iframe>
<script>
    const iframe = document.getElementById('iframe')
    iframe.onload = () = > {
        iframe.contentWindow.pastMessage('Sent data'.'http://received address')}</script>
window.parent.pastMessage('Sent data'.'http://received address') 
Copy the code
/ / receiver
window.addEventListener('message'.(e) = >{
    console.log('Data received:' + e.data
})
Copy the code

6. JSONP

The idea is to request JSON data from the server without the same origin policy by adding a <script> tag. When the server receives the request, it returns the data in a callback function. Such as axios.

It only supports GET requests and is not secure, and may encounter XSS attacks, but it has the benefit of being able to request data from older browsers or websites that do not support CORS

<script>
    let script = document.createElement('script')
    script.type = 'text/javascript'
    script.src = 'http://juejin.com/xxx?callback=handleCallback'
    document.body.appendChild(script)
    
    function handleCallback(res){
        console.log(res)
    }
</script>
Copy the code

The server returns and executes immediately

handleCallback({ code: 200.msg: 'success'.data: []})Copy the code

What happens to cookies when you cross domains?

Cookie: Cookie: Cookie: Cookie: Cookie: Cookie: Cookie

Set-Cookie: widget_session=123456; SameSite=None; Secure
Copy the code

SameSite has three values:

  • strict: In strict mode, the use of cookies is completely prohibited
  • lax: loose mode, allowing the use of cookies in some cases,Cross domain is fine, a TAB jump, link TAB, GET submitted form
  • none: Cookies will be sent in any case, but the Secure attribute must be set at the same time, meaning that the security context, cookies, is requiredOnly HTTPS can be used, otherwise invalid

Chrome 80 defaults to None, followed by lax

However, this has been removed in the latest Chrome91 version, so pre-91 versions will still work

If the Chrome or Edge version is greater than 91 and less than 94, you can use the Command line flag supported by Chromium

  • Right-click Chrome or Edge and select Properties
  • At the end of the Target attribute
 --disable-features=SameSiteByDefaultCookies,CookiesWithoutSameSiteMustBeSecure
Copy the code

It is officially said that comman-line will also be removed in version 94

The official line is to leave both options open to attack by letting developers control them

conclusion

I think we should try to stay in the same domain if we can not cross domains. We should use the front-end proxy for development and Nginx proxy for deployment. Or set the cross-domain header in the request. The principle is the same, but the response header sets the cross-domain parameters

Praise support, hand stay fragrance, and have glory yan

Thanks for seeing this, come on!

reference

Juejin. Cn/post / 691615…