1. Same-origin policy
(1) What is the same-origin policy
Why do we talk about the same origin policy first, because what happens when you cross domains is you violate the same origin policy
Refer to MDN for an explanation of homology
The same origin policy is an important security policy that restricts how an Origin document or the scripts it loads can interact with resources from another source. It can help block malicious documents and reduce the number of vectors that can be attacked.
(2)homologousthedefine
Two urls are cognate if their protocol, port (en-us) (if specified), and host are the same. This scheme is also known as a “protocol/host/port tuple”, or simply “tuple”. (” tuple “refers to the whole of a group of items, in the general form of double/triple/quadruple/quintuple/etc.).
The following table gives the comparing with the URL http://store.company.com/dir/page.html source example:
URL | The results of | why |
---|---|---|
http://store.company.com/dir2/other.html |
homologous | Only the path is different |
http://store.company.com/dir/inner/another.html |
homologous | Only the path is different |
https://store.company.com/secure.html |
failure | Agreement is different |
http://store.company.com:81/dir/etc.html |
failure | Different ports (http:// The default port is 80) |
http://news.company.com/dir/other.html |
failure | The host different |
2. How to solve cross-domain problems?
Cross-domain problems occur not because the server does not return the data in response, but because the browser restricts it
(1) the json
The json principle
Web pages can get JSON data dynamically generated from other sources by taking advantage of the <script> tag’s lack of cross-domain limitations. JSONP requests must be supported by the other party’s server.
Remark:
Comparison between JSONP and AJAX JSONP is the same as AJAX in that the client sends a request to the server to obtain data from the server. But AJAX is a same-origin policy,JSONP is a non-same-origin policy (cross-domain request)
The whole implementation process of JSONP
Advantages and disadvantages JSONP is simple and compatible, and can be used to solve the problem of cross-domain data access in mainstream browsers. The disadvantages are that supporting only get methods is limited and insecure and may be subject to XSS attacks.
- Declare a callback function whose name (such as show) is passed to the server that requests data across domains and whose parameter is to fetch the target data (the data returned by the server).
- Create a
- Once the server receives the request, it needs to do something special: concatenate the name of the function passed in with the data it needs to give you into a string, for example: the name of the function passed in is show, and the data it prepares is show(‘ I like ping-pong ‘).
- Finally, the server returns the data to the client through HTTP protocol, and the client calls the callback function (show) previously declared to operate on the returned data.
/ / encapsulates the json
jsonp.html
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = s, initial - scale = 1.0">
<title>Document</title>
</head>
<body>
<script>
function jsonp({ url, params, callback }) {
return new Promise((resolve, reject) = > {
let script = document.createElement('script');
params = JSON.parse(JSON.stringify(params));
let arrs = [];
for (let key in params) {
arrs.push(`${key}=${params[key]}`);
}
arrs.push(`callback=${callback}`);
script.src = `${url}?${arrs.join('&')}`;
document.body.appendChild(script);
window[callback] = function (data) {
resolve(data);
document.body.removeChild(script); }})}// front-end call
jsonp({
url: 'http://localhost:3000/hobby'.params: {
wd: 'I Love play pingpang'
},
callback: 'show'
}).then(data= > {
console.log(data)
})
</script>
</body>
</html>
Copy the code
// The back-end code uses Express to create a back-end service
server.js
// Express is used here
var express = require('express');
var router = express.Router();
var app = express();
router.get('/hobby'.function(req,res,next) {
// The data to respond back
let data = {
username : 'zhangsan'.password : 123456
}
let {wd , callback} = req.query;
console.log(wd);
console.log(callback);
// Call the callback function and respond
res.end(`${callback}(The ${JSON.stringify(data)}) `);
})
app.use(router);
app.listen(3000);
Copy the code
Start the service using node Server
(2) CORS (Cross-origin Resource Sharing)
CORS requires both browser and backend support. IE8 and IE9 need to use XDomainRequest to realize that the browser will automatically carry out CORS communication. The key to realize CORS communication is the back end. As long as the backend implements CORS, it implements cross-domain. To enable CORS, set access-Control-allow-Origin on the server. This attribute indicates which domain names can access resources. If a wildcard is set, all websites can access resources. Although setting up CORS has nothing to do with the front end, solving cross-domain problems in this way can result in two cases of simple and complex requests being sent.
A simple request
As long as the following two conditions are met, it is a simple request
Condition 1: Use one of the following methods:
- GET
- HEAD
- POST
Condition 2: The value of the content-Type is limited to one of the following:
- text/plain
- multipart/form-data
- Any XMLHttpRequestUpload object in the Application/X-www-form-urlencoded request does not register any event listeners;
Complex request
A request that does not meet the above conditions is a complex request. A CORS request of a complex request will add an HTTP query, called “precheck” request, before formal communication. This request is the option method, through which the server can know whether to allow cross-domain request. When a PUT request is sent to the background, it is a complex request. The background configuration is as follows:
// Which method is allowed to access me
res.setHeader('Access-Control-Allow-Methods'.'PUT')
// Precheck the survival time
res.setHeader('Access-Control-Max-Age'.6)
// OPTIONS request no processing
if (req.method === 'OPTIONS') {
res.end()
}
// Define what is returned in the background
app.put('/getData'.function(req, res) {
console.log(req.headers)
res.end('I like playing table tennis')})Copy the code
// Front-end code
cors.html
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Document</title>
</head>
<body>
<script>
let xhr = new XMLHttpRequest();
document.cookie = 'name=hw';
xhr.withCredentials = true; // Set whether cookies are included in the front end
xhr.open('PUT'.'http://localhost:4000/getData'.true);
xhr.setRequestHeader('name'.'hw');
xhr.onreadystatechange = function() {
if(xhr.readyState === 4) {
if(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) {
console.log(JSON.parse(xhr.response));
console.log(xhr.getResponseHeader('name'))
}
}
}
xhr.send();
</script>
</body>
</html>
Copy the code
// Create a port service for the front-end
let express = require('express');
let app = express();
app.use(express.static(__dirname))
app.listen(3000)
Copy the code
// Back-end code
cors.js
// Back-end code
let express = require('express')
let app = express()
let whitList = ['http://127.0.0.1:3000'] // Set the whitelist
app.use(function(req, res, next) {
let origin = req.headers.origin
if (whitList.includes(origin)) {
// Set which source can access me
res.setHeader('Access-Control-Allow-Origin', origin)
// Which header is allowed to visit me
res.setHeader('Access-Control-Allow-Headers'.'name')
// Which method is allowed to access me
res.setHeader('Access-Control-Allow-Methods'.'PUT')
// Cookies are allowed
res.setHeader('Access-Control-Allow-Credentials'.true)
// Precheck the survival time
res.setHeader('Access-Control-Max-Age'.6)
// Allow return headers
res.setHeader('Access-Control-Expose-Headers'.'name')
if (req.method === 'OPTIONS') {
res.end() // OPTIONS request no processing
}
}
next()
})
app.put('/getData'.function(req, res) {
let data = {
username : 'zhangsan'.password : 123456
}
console.log(req.headers)
res.setHeader('name'.'jw') // Return a response header that needs to be set in the background
res.end(JSON.stringify(data))
})
app.get('/getData'.function(req, res) {
console.log(req.headers)
res.end('hhhhaha')
})
app.listen(4000)
Copy the code
// In the browser address bar, enter 127.0.0.1:3000/ cers.html
You can see that there are two getData requests
PUT request
The response Headers section
The Request Headers section
This implements a cross-domain request access from port 3000 to port 4000
The OPTIONS request
(3) Nginx solves cross-domain problems
In many ways to solve the cross domain, it is inevitable to need the support of the server, using Nginx can be pure front-end to solve the request cross domain problem
server
{
listen 3002;
server_name localhost;
location /ok {
proxy_pass http://localhost:3000;
# specify methods that are allowed across domains, * for all
add_header Access-Control-Allow-Methods *;
# precheck the cache of the command, if not cached will send two requests each time
add_header Access-Control-Max-Age 3600;
# Cookie requests require this field and set to true
add_header Access-Control-Allow-Credentials true;
# indicates that this domain is allowed to make cross-domain calls (the domain name and port from which the client sends the request)
# $http_origin does not use * because requests with cookies do not support *
add_header Access-Control-Allow-Origin $http_origin;
# represents the dynamic retrieval of fields in the request header
add_header Access-Control-Allow-Headers
$http_access_control_request_headers;
The request will not be sent until the precheck command passes
Check whether the type of request is a precheck command
if ($request_method = OPTIONS){
return200; }}}Copy the code