Cross-Domain

When establishing HTML rules, for security reasons, a website from one origin is not allowed to interact with resources from another origin, and the browser sets this rule as the same-origin policy.

The same origin refers to websites having the same domain, that is, the protocol, host, and port are the same.

Embedding cross-origin resources is allowed, but the browser restricts JavaScript from interacting with the loaded content, such as embedded <script>, <img>, <link>, <iframe>, among others.

Restricted Scenarios

  • XHR requests cannot be sent.
  • Modification of cross-origin request resources is impossible.
  • Cookie and LocalStorage from different origins cannot be accessed.

Cross-Domain Solutions

JSONP for Cross-Domain Data Requests

Since <script> can request cross-origin resources, a callback function name can be appended dynamically to a <script> tag using the DOM, which will be called upon completion of the request.

// Frontend
function jsonpHandle(data){console.log(data);} // Function definition. The function will be called with parameters upon completion of the request.
var url = "http://127.0.0.1/test.php?callback=jsonpHandle";
var obj = $('<script><\/script>');
obj.attr("src",url);
$("body").append(obj); // Dynamically add a script
// Backend Implementation
$data = ["a" => 1, "b" => 2];
$callback = $_GET['callback'];
return $callback."(".json_encode($data).")";

CORS for Cross-Domain Requests

For simple requests, the browser will directly send a CORS request by adding the Origin request header in the header. Likewise, in the response header, the server will return the relevant CORS header fields it has set, with the Access-Control-Allow-Origin field allowing the source to make cross-origin requests. When sending the request, the browser will specify the requesting source in the Origin request header, and if the server allows cross-origin requests from that source, it will return successfully. For non-simple requests, the browser will first automatically send an OPTIONS request. If the server supports the request, it will send the actual request to the backend. Otherwise, if the server does not support the request, an error will be logged in the console.

// Response Headers
header('Content-Type: text/html;charset=utf-8');
header('Access-Control-Allow-Origin:http://localhost:8080'); // Use * to allow requests from any origin
header('Access-Control-Allow-Methods:POST,GET'); // Allowed request types
header('Access-Control-Allow-Credentials: true'); // Indicates whether the response can include credentials
header('Access-Control-Allow-Headers: Content-Type,Origin,Refer'); // Allow custom request headers

Nginx Proxy

By using proxy, listening on the same port, and adding different paths, cross-origin access between different services can be achieved.

location /test { proxy_pass http://127.0.0.1:81; }

Image Ping

Simply create a new <img> and include some basic data in the address. This method only supports get requests and can only send requests to the server unilaterally, which is commonly used for tracking ad impressions and is also frequently employed in XSS attacks to obtain cookies.

<img src="http://127.0.0.1?key=value">

Same primary domaindocument.domain

For example, for www.example.com and abc.example.com, their primary domain is the same.

document.domain = "example.com"; // Same primary domain
var ifrWin = document.getElementById("ifr").contentWindow; // Can manipulate iframe

Sharing data withwindow.name

Different domain iframes store shared information in window.name, this method only applies to cross-origin communication between two iframes.

window.name = JSON.stringify({"a":1,"b":2})

window.postMessage

Use window.postMessage to send messages to other window objects, regardless of whether the window object belongs to the same origin or a different origin. This method cannot be used to exchange data with the server.

// Main window
window.frames[0].postMessage({"a":1},"http://127.0.0.1:81")
// Iframe // For security reasons, verify the source
window.addEventListener('message',(event)=>{
  if(event.origin === "http://127.0.0.1") console.log(event.data);
});

Question of the Day

https://github.com/WindrunnerMax/EveryDay