First, the classic question: why cross-domain?
Let’s break it down
-
Who appears across domains? == “browser!
-
Why? == Indicates the same-origin policy
-
Same-origin policy?
- The Same Origin Policy (SOP) is a convention introduced by Netscape in 1995. It is the core and most basic security function of the browser. Without the Same Origin policy, the browser is vulnerable to the Same origin policy
XSS
,CSFR
Such attacks. - Same-origin == refers to the fact that only one difference between protocols, domain names, and ports will cause cross-domain problems
- The Same Origin Policy (SOP) is a convention introduced by Netscape in 1995. It is the core and most basic security function of the browser. Without the Same Origin policy, the browser is vulnerable to the Same origin policy
-
Purpose: Simply disallow “document” or scripts from different sources to read or set certain properties of the current “document”.
-
-
The solution?
-
The front end acts as a proxy server
-
Cross-domain Technology -CORS (CrossOrigin Resources Sharing, Cross-source Resource Sharing) (Recommended)
CORS
, it isHTML5
Is a feature that defines a way for the browser and server to interact to determine whether cross-domain requests are allowed.- How it works: Once the browser discovers that an AXIos request is across domains, it automatically adds some additional headers and sometimes an additional request, but the user is unaware of it. Based on these additional values, the server decides whether to approve the request or not.
-
JSONP
- Changing the request
DataType: 'jSONp ', // request type is JSONp
- Principle: JSONP is added dynamically
-
/ / front end to achieve $. Ajax ({url: 'http://www.domain2.com:8080/login', type: "get", dataType: 'the json, / / requests for the json jsonpCallback: "OnBack ", // custom callback name data: {}}); / / the background to realize @ ControllerAdvice (basePackages = "com. ZKN. Learnspringboot. Web. Controller") public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice{ public JsonpAdvice() { super("callback","jsonp"); }}Copy the code
- Changing the request
-
-
Solve the optimal solution == “CORS”
- Compared to the
jsonp
Can only be used for GET requestscors
This applies to all requests jsonp
The advantage is that it can support older browsers, and can not supportcors
Web site requests data.
- Compared to the
Two, how to solve?
-
Front-end Proxy Server (VUE)
-
Vue.config. js ==> Configuration file
-
// Configure proxy devServer: {port: 9086, open: false, overlay: {warnings: false, errors: true}, proxy: {"/dev_api": {target: "http://11.111.111.11:8000/", "= = here should state their access code changeOrigin: true, pathRewrite: {" ^ / dev_api" : ""}}}},Copy the code
-
-
Configure baseUrl in request.js
-
let instance = axios.create({ baseURL: "/dev_api", withCredentials: True, // send cookies when cross-domain requests timeout:5000,}) The "/" before dev_api must not be omitted. Don't ask me how I know it. // Dev_api should be the same as the one above, but you can give it your own nameCopy the code
-
-
Local operation is relatively smooth, but the project package to the server on the need to address a debugging, with the background coordination!
-
-
Cross-domain Technology -CORS (Recommended)
-
Introduction to the
- CORS communication is done automatically by the browser without user involvement
- For developers alike, CORS communication is no different than normal AJAX communication, with exactly the same code. As soon as the browser discovers that an AJAX request crosses domains, it automatically adds some additional header information
- Therefore, the key to realize CORS is the server. As long as the server implements CORS interface, it can communicate across domains
-
Simple request (GET POST)
-
When the browser detects a cross domain, it automatically adds an Origin field to the request header
-
GET /cors HTTP/1.1 Origin: http://api.bob.com Host: api.alice.com Accept-language: en-us Connection: Keep alive - the user-agent: Mozilla / 5.0...Copy the code
Origin
The field indicates which domain the request is from (protocol + domain + port)
-
-
If Origin is found to be the specified source (in the whitelist), the server responds with success and several more information fields in the response header
-
Access-control-allow-origin: access-Control-allow-origin: access-Control-allow-origin: access-Control-allow-origin: http://api.bob.com // This field is optional whether cookie access-Control-allow-credentials are allowed: True /* The getResponseHeader() method of the XMLHttpRequest object returns only six basic fields from the server on a CORS request: Cache-control, Content-language, Content-Type, Expires, Last-Modified, Pragma. If you want to get other fields, you must specify access-Control-expose-headers. The above example specifies that getResponseHeader('FooBar') can return the value of the FooBar field. */ Access-Control-Expose-Headers: FooBarCopy the code
-
-
If Origin is not found within the license, the server returns a normal Http response and throws the error XMLHttpRequest…
-
-
How to configure it?
-
The key to implementing CORS is the server, so the front end only needs to configure the **withCredentials** attribute
-
CROS requests do not contain cookie information by default. If we want to include cookie information, we must set the withCredentials property to true in the request
-
// Create axios instance ===> Proxy server must write /!!!! let instance = axios.create({ baseURL: "/dev_api", withCredentials: true, // send cookies when cross-domain requests timeout:5000, }) instance.defaults.withCredentials = true; // Allow cookie ==> this is too criticalCopy the code
-
-
Also note that if you want to send cookies access-Control-allow-origin cannot be set to *****!! This means that you must specify a specific domain name that is consistent with the requested page
-
-
Third, Token, Cookie and CORS love and hate
-
Where does user authentication come in?
- As we all know, when the client repeatedly requests data from the server, the server needs to repeatedly query the user name and password from the database and compare them to judge whether the user name and password are correct, and make corresponding prompts.
- However, this will undoubtedly increase the operating pressure on the server side. Can there be a way to verify that the user is the same as the previous user without having to query the database every time the client requests data to determine whether the user name and password are correct?
- In order to avoid a large number of queries database to reduce the operating pressure on the server side of the token mechanism emerged
-
How does the token work?
-
token
-
After the front-end login succeeds, the backend returns the token
-
The token is processed by the front end, stored and put in the request header every time a request is made the token is put in the request header
-
The instance. The interceptors. Request. Use ((config) = > {/ / judge some interface does not need token if (! Config. NoAuthorization) {/ / join token let token. = RootStore userStore. AllData. AccessToken; if (token) { config.headers.Authorization = `Bearer ${token}`; } } return config; }, (err) => { console.log(err); });Copy the code
-
-
-
Cookies are stored in the
-
The backend token (sessionId) is stored in the browser Cookie
-
The front end request automatically passes the sessionId from the cookie to the back end
-
-
-
When the token cookie encounters cross-domain 🤦
-
token
- Cross domain? We can go directly to the server
Access-Control-Allow-Origin
Set it to ***** front-endwithCredentials
Properties forfalse
- That is, all origin access is allowed
- Cross domain? We can go directly to the server
-
cookie
-
Theoretically, we can follow the method of token, but
-
The cookie access-Control-allow-origin cannot be set to *****!! This means that you must specify a specific domain name that is consistent with the requested page
-
That means we need to specify a specific domain name to access and we need to tell the back end what our domain name is and whitelist it, right
-
The most important thing is to configure the **withCredentials** property on the front end to be true
-
// Create axios instance ===> Proxy server must write /!!!! let instance = axios.create({ baseURL: "/dev_api", withCredentials: true, // send cookies when cross-domain requests timeout:5000, }) instance.defaults.withCredentials = true; // Allow cookie ==> this is too criticalCopy the code
-
-
At the same time, set access-Control-allow-credentials to true on the back-end
-
So under the given Origin URL we can implement login and resolve cross-domain
-
A small problem
-
Only when the browser accesses the path under the server address, the browser will automatically bring cookies, so what should we do if we cannot bring cookies for local debugging?
-
Solution 1: Use server proxy == Use the server proxy to solve cross-domain problems
- Disadvantages: But the server needs to be modified baseURL
-
Scheme 2: Write to the local console using the sessionId passed to the server ==>
- If not, write
- Disadvantages: The sessionId update time is short and does not apply to frequently changing sesionId
-
-
-
-
conclusion
- As can be seen from the length, token is more convenient than cookie. The fact that cookies have many limitations and troubles leads to the trouble of comparison
- In terms of security: it’s not a hassle security both use tokens to transmit, but in a different way, the security is still about the same
-
References:
- What is cross-domain and why are there cross-domain problems – IT road white – Blogs.com)
- CORS Communications — JavaScript Standard Reference Tutorial (Alpha) (Ruanyifeng.com)