Jin SAN Yin Si, this is the recruitment peak, many friends have sent me the interview questions recently, I hereby leave notes and share, I hope to help you to improve.
What is cross-domain?
Access-cotro-allow-origin = access-cotro-allow-origin = access-cotro-allow-origin In fact, what we usually mean by cross-domain is narrowly defined, a class of request scenarios that are restricted by the browser’s same-origin policy. So what is the same origin policy?
What is the same origin policy?
The cornerstone of browser security isThe same origin policy(Same-origin policy). Netscape introduced the browser. Currently, all browsers implement this policy. By homology we meanProtocol + Domain name + PortThey are the same. Even if two different domain names point to the same IP address, they are not identical. It is the core and most basic security function of the browser. Without the same origin policy, the browser is vulnerable to XSS, CSFR and other attacks.Copy the code
“Homology” means “three of the same”.
Same protocol same domain name same port sameCopy the code
For example:
For example, http://www.a.com:3000/index.html, the agreement is http://, a domain name is www.a.com, port is 3000 (we often see url: no, because the default port 80 can be omitted).
Common cross-domain scenarios
URL Description Whether to allow communication http://www.a.com/a.js http://www.a.com/b.js the same domain name, Different file or path to allow, belongs to the homologous http://www.a.com/lab/c.js http://www.a.com:8000/a.js http://www.a.com/b.js the same domain name, Different ports cannot use the same domain name http://www.a.com/a.js https://www.a.com/b.js. Different protocols http://www.a.com/a.js http://192.168.4.12/b.js the domain name and domain name must be the same IP address. http://www.a.com/a.js http://x.a.com/b.js The primary domain must be the same. http://a.com/c.js http://www.a.com/a.js http://www.b.com/b.js Different domain names are not allowedCopy the code
- The same origin policy restricts the following behaviors:
Cookie, LocalStorage, and IndexDB cannot be read. (2) DOM cannot be obtained. (3) AJAX requests cannot be sent.Copy the code
Cross-domain solutions
Hash + iframe 5. Window. name + iframe 6. PostMessage Nodejs middleware proxy is cross-domain. 9. WebSocket protocol is cross-domainCopy the code
1. Cross domains through JSONP
Usually, in order to reduce the load of the Web server, we separate static resources such as JS, CSS and IMG to another server with an independent domain name, and then load static resources from different domain names in the HTML page through corresponding tags, which are allowed by the browser. Based on this principle, we can dynamically create script. Request a reference url to achieve cross-domain communication. Jsonp takes advantage of this feature.
The advantages and disadvantages:
- JSONP is a common way for servers and clients to communicate across sources. The biggest feature is simple to apply, the old browser all support, server transformation is very small.
- Only get can be implemented for one request,Insecure vulnerable to XSS attacks
Example: When we search on Baidu, we will find that Baidu calls are also implemented through JSONP. As I can find in baidu’s cross-domain, F12 development mode and Network, it is realized by JS as shown in the figure below.
So let’s simulate calling this interface. https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/suwd=&json=1&p=3&sid=1460_21119_28205_28131_28266_27245_22159&req=2&bs =%E8%B7%A8%E5%9F%9F&csor=0&cb=jQuery110205514934443247432_1553744466531&_=1553744466532
Simplified as: https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=a&cb=show below may be used
<script>
function show(params) {
console.log(params);
}
</script>
<script src="https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=a&cb=show"></script>
Copy the code
As shown below, output can be called normally:
Simulated JSONP code:
function jsonp({url,params,cb}) {
return new Promise((resolve, reject) => {
let script = document.createElement('script');
window[cb] = function(params) { resolve(params); } params = {... params,cb};let arrs = [];
for(let key in params){
arrs.push(`${key}=${params[key]}`);
}
script.src = `${url}?${arrs.join('&')}`;
document.body.appendChild(script);
}); };
jsonp({
url: 'https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su',
params:{wd:'a'},
cb:'show'
}).then(data=>{
console.log('JSONP cross-domain request data is:',data);
});Copy the code
2.) jquery ajax: $. Ajax ({url:'https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su'.type: 'get',
dataType: 'jsonp'JsonpCallback:"show"Data: {wd:'a'}});Copy the code
3.) Vue.js: This.$http.jsonp('https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su', {
params: {wd:'a'},
jsonp: 'show'}).then((res) => {
console.log(res);
})
Copy the code
2.CORS
CORS is a W3C standard, cross-Origin Resource Sharing, that allows browsers to send messages across source servers
XMLHttpRequest
Requests, thus overcoming AJAX only
homologousRestrictions on use.
Ps: Common cross-domain request: Only access-Control-allow-origin is required on the server, and the cookie request is required on both the front and back ends. Because of the same-origin policy restriction, the cookie read is the cookie of the domain where the cross-domain request interface resides, not the current page.
The advantages and disadvantages:
- Currently, all browsers support this functionality (IE8+ : IE8/9 requires the use of XDomainRequest objects to support CORS), and CORS has become a mainstream cross-domain solution.
- The entire CORS communication process is completed automatically by the browser without user participation. For developers, CORS communication is no different from same-origin AJAX communication, and the code is exactly the same. As soon as the browser discovers that an AJAX request crosses the source, it automatically adds some additional headers, and sometimes an additional request, but the user doesn’t feel it.
- CORS serves the same purpose as JSONP, but is more powerful than JSONP. The json support only
GET
Requests, CORS supports all types of HTTP requests. JSONP has the advantage of supporting older browsers and being able to request data from sites that do not support CORS.
Two kinds of requests:
Browsers classify CORS requests into two categories: Simple request and not-so-simple Request.
As long as the following two conditions are met, it is a simple request. Any request that does not meet both of the following conditions is a non-simple request.
1) The request method is one of the following: HEADGETPOST (2) The HTTP header does not exceed the following fields: acceptAccept-languagecontent-languagelast -Event- idContent-type: Application/X-www-form-urlencoded, multipart/form-data, text/plain are limited to three valuesCopy the code
Simple request:
For simple requests, the browser directly issues CORS requests. Specifically, add an Origin field to the header information.
Non-simple request:
Requests that have special requirements on the server, such as a PUT or DELETE request method, or a Content-Type field of application/ JSON.
CORS requests that are not simple requests are preceded by an HTTP query request, called a “preflight” request.
The browser asks the server if the domain name of the current web page is on the server’s license list, and what HTTP verb and header fields can be used. The browser issues a formal XMLHttpRequest request only if it receives a positive response; otherwise, an error is reported.
{ host: 'localhost:4000',
connection: 'keep-alive'.'content-length': '0',
origin: 'http://localhost:3002',
name: 'lee1'.'user-agent': 'the Mozilla / 5.0 (Windows NT 10.0; Win64; X64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36',
accept: '* / *',
referer: 'http://localhost:3002/2cors.html'.'accept-encoding': 'gzip, deflate, br'.'accept-language': 'zh-CN,zh; Q = 0.9 ',
cookie: 'name=lee' }
Copy the code
(1) Access – Control – Allow – Origin
This field is required. Its value is either the value of the Origin field at the time of the request, or an *, indicating acceptance of requests for any domain name.
(2) Access – Control – Allow – Credentials
This field is optional. Its value is a Boolean value indicating whether cookies are allowed to be sent. By default, cookies are not included in CORS requests. If set to true, the server explicitly approves that cookies can be included in the request and sent to the server. This value can only be set to true if the server does not want the browser to send cookies.
(3) the Access – Control – Expose – Headers
This field is optional. In CORS requests, the getResponseHeader() method of the XMLHttpRequest object takes only six basic fields: 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.
WithCredentials attribute
CORS requests do not send cookies and HTTP authentication information by default. To send cookies to the server, specify the access-Control-allow-credentials field with the server’s permission.
Access-Control-Allow-Credentials: trueCopy the code
The developer must turn on the withCredentials attribute in the AJAX request.
var xhr = new XMLHttpRequest(); xhr.withCredentials = true;Copy the code
Otherwise, the browser won’t send a Cookie, even if the server agrees to do so. Or, if the server asks for a Cookie, the browser won’t handle it.
However, if the withCredentials setting is omitted, some browsers still send cookies together. In this case, you can explicitly disable the withCredentials.
xhr.withCredentials = false; Copy the code
Note that access-Control-allow-Origin cannot be set to an asterisk if cookies are to be sent, and must specify an explicit domain name consistent with the requested web page. At the same time, cookies still follow the same origin policy, only the Cookie set with the server domain name will be uploaded, cookies of other domain names will not be uploaded, and (cross-source) document. Cookie in the original web page code can not read cookies under the server domain name.
(4) the Access – Control – Request – Method
This field is required to list which HTTP methods are used by the browser for CORS requests, in this example PUT.
(5) Access – Control – Request – Headers
This field is a comma-delimited string that specifies the additional header fields that the browser will send for CORS requests
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 1728000Copy the code
(6) the Access – Control – Allow – the Methods
This field is required, and its value is a comma-separated string indicating all methods supported by the server for cross-domain requests. Notice that all supported methods are returned, not just the one requested by the browser. This is to avoid multiple “pre-check” requests.
(7) Access – Control – Allow – Headers
The access-Control-allow-HEADERS field is required if the browser Request includes the access-Control-request-HEADERS field. It is also a comma-separated string indicating all header information fields supported by the server, not limited to those requested by the browser in precheck.
(8) Access – Control – Allow – Credentials
This field has the same meaning as a simple request.
(9) Access – Control – Max – Age
This field is optional and specifies the validity period of the precheck request, in seconds. In the result above, the validity period is 20 days (1728000 seconds), which allows the response to be cached for 1728000 seconds (20 days), during which time another precheck request is not issued.
Simulation:
Front-end setup JS;
Js in a HTML page
let xhr = new XMLHttpRequest;
document.cookie = 'name=lee'; // Cookies cannot cross domain xhr.withcredentials =true; //
xhr.open('PUT'.'http://localhost:4000/getData'.true);
xhr.setRequestHeader('name'.'lee1');
xhr.onreadystatechange = function () {
if(xhr.readyState === 4){
if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) {
console.log(xhr.response);
} } }
xhr.send();Copy the code
The back-end is simulated with Node:
A. s. (for can invoke http://localhost:4000/getData http://localhost:3002/a.html to start page belongs to the cross domain)
let express = require('express');
letapp = express(); app.use(express.static(__dirname)); app.listen(3002);Copy the code
b.js
let express = require('express');
let app = express();
let whiteList = ['http://localhost:3002'];
app.use(function (req,res,next) {
let origin = req.headers.origin;
if(whitelist.includes (origin)){// Set which source can access res.setheader ('Access-Control-Allow-Origin', origin); // Which header is allowed to access me res.setheader ("Access-Control-Allow-Headers"."name,Content-Type,X-Requested-With"); // Cookie res.setheader ('Access-Control-Allow-Credentials'.'true'); Res.setheader ("Access-Control-Allow-Methods"."PUT"); Res.setheader ("Access-Control-Max-Age", 1800); Res.setheader ("Access-Control-Expose-Headers"."name"); // option prechecks the request and sometimes does not indicate that the request is for questioningif(req.method === 'OPTIONS'){ res.end(); } } next(); }) app.put('/getData'.function (req, res) {
console.log(req.headers);
// res.setHeader('name'.'hello lee'); res.end(`getData`); }); app.get('/getData'.function(req,res) { console.log(req.headers); res.end(`getData`); }); app.use(express.static(__dirname)); app.listen(4000);Copy the code
3. Document. domain + iframe cross-domain
This solution applies only to cross-domain scenarios where the primary domain is the same and the subdomains are different (the level-1 domain name of web pages is the same, but the level-2 domain name is different). Implementation principle: two pages through JS forced document.domain as the base of the primary domain, to achieve the same domain.
1.) parent window :(www.a.com/a.html)
<iframe id="iframe" src="http://child.a.com/b.html"></iframe>
<script>
document.domain = 'a.com';
var user = 'admin';
</script>Copy the code
2.) sub-window :(child.a.com/b.html)
<script>
document.domain = 'a.com'; // Get the parent window variable alert('get js data from parent ---> ' + window.parent.user);
</script>Copy the code
4. location.hash
Implementation principle: A and B communicate with each other across domains through the middle page C (and C and A are co-domains). Three pages, different fields use iframe location.hash to transfer values, the same fields directly js access to communicate.
A domain: A.html -> B domain: B.html -> A domain: C.HTML, A and B different domain can only hash value one-way communication, B and C are also different domain can only one-way communication, but C and A are the same domain, so C can access all objects on A page through parent. Parent.
1.) A.HTML (www.a.com/a.html)
<iframe id="iframe" src="http://www.b.com/b.html" style="display:none;"></iframe>
<script>
var iframe = document.getElementById('iframe'); / / to the b.h HTMLhashvaluesetTimeout(function() {
iframe.src = iframe.src + '#user=admin'; }, 1000); // callback methods open to homologous C.HTMLfunction onCallback(res) {
alert('data from c.html ---> ' + res);
}
</script>Copy the code
2.) B.HTML (www.b.com/b.html)
<iframe id="iframe" src="http://www.a.com/c.html" style="display:none;"></iframe>
<script>
var iframe = document.getElementById('iframe'); // listen for a.htmlhashValue, which is passed to C.html window.onhashchange =function () {
iframe.src = iframe.src + location.hash;
};
</script>Copy the code
3.) C. HTML (www.a.com/c.html)
<script> // Listen for b.HTML incominghashValue window. Onhashchange =function() {/ / and by operating with domain a.h HTML js callback, the results back to the window. The parent, the parent. OnCallback ('hello: ' + location.hash.replace('#user='.' '));
};
</script>Copy the code
5. Window. name + iframe cross domains
The browser window has
window.name
Properties. The most important feature of this property is that, regardless of whether the same source, as long as the previous page in the same window set this property, the next page can read it.It also supports very long name values (2MB).
The parent window opens a child window that loads a web page from a different source, which writes information to the window.name property.
window.name = data; Copy the code
Next, the child window jumps back to a web address in the same domain as the main window.
location = 'http://parent.url.com/xxx.html'; Copy the code
The main window can then read the window.name of the child window.
var data = document.getElementById('myFrame').contentWindow.name; Copy the code
The advantage of this approach is that window.name is very large and can hold very long strings; The disadvantage is that you must listen for changes in the window.name property of the child window, which affects web page performance.
1.) A.HTML (www.a.com/a.html)
var proxy = function(url, callback) {
var state = 0;
var iframe = document.createElement('iframe'); // Load the cross-domain page iframe.src = url; // The onload event is triggered twice, the first time the cross-domain page is loaded, and the data is saved in window.name iframe.onload =function() {
if(state = = = 1) {/ / second onload after the success of the page (sympatric c), read the same domain window. The name of the callback data (iframe. ContentWindow. Name); destoryFrame(); }else if(state = = = 0) {/ / first onload (cross-domain pages) after the success, switch to sympatric agent iframe page. The contentWindow. Location ='http://www.a.com/c.html'; state = 1; }}; document.body.appendChild(iframe); // After the data is retrieved, the iframe is destroyed to free memory; This also ensures security (not accessed by other fields frame JS)function destoryFrame() {
iframe.contentWindow.document.write(' '); iframe.contentWindow.close(); document.body.removeChild(iframe); }}; // request cross-domain B page data proxy('http://www.b.com/b.html'.function(data){
alert(data);
});Copy the code
2.) c.html :(www.a.com/c.html intermediate proxy page, the same domain as a.html, the content is empty.
3.) B.HTML (www.b.com/b.html)
<script>
window.name = 'This is b.html data! ';
</script>Copy the code
6. PostMessage across domains
HTML5 addresses this problem by introducing a new API: Cross-document Messaging.
The API adds a window.postMessage method to window objects, allowing cross-window communication regardless of whether the two Windows are identical.
postMessage
The first parameter of the method is the specific information content, and the second parameter is the origin of the window to receive the message, that is, “protocol + domain + port”. Or you can set it to
*
Is sent to all Windows without limiting the domain name.
It can be used to solve the following problems:
A.) data transfer between the page and the new window it opens b.) message transfer between multiple Windows c.) message transfer between the page and nested iframe d.) cross-domain data transfer for the three scenarios aboveCopy the code
For example, a.js b.js uses node to enable two interfaces with different port numbers to simulate a local implementation across domains
The parent window
localhost:4001/a.html
To a child window
localhost:4002/b.html
Send a message, call
postMessage
The method will do. Both parent and child Windows can pass
message
Event to listen for messages from the other party.
1) a.h HTML
<iframe src="http://localhost:4002/b.html" frameborder="0" id="frame" onload="load()" ></iframe>
<script>
function load(params) {
let frame = document.getElementById('frame');
frame.contentWindow.postMessage('From page A to page B'.'http://localhost:4002');
window.onmessage = function(e) {// Both parent and child Windows can listen for messages from each other via message events. console.log(e.data,'a.html'); }}Copy the code
2)b.html
window.onmessage = function(e) {// Both parent and child Windows can listen for messages from each other via message events. console.log(e.data,'b.html'); // The child window references the parent window via the event.source property and then sends a message. The Event. origin attribute filters messages that are not sent to this window. e.source.postMessage('Send a message from B to A',e.origin);
}
Copy the code
3) A.js (Running A.js)
let express = require('express');
letapp = express(); app.use(express.static(__dirname)); app.listen(4001);Copy the code
4) B.js (node B.js)
let express = require('express');
letapp = express(); app.use(express.static(__dirname)); app.listen(4002);Copy the code
The event object for the Message event provides the following three properties.
event.source
: Window for sending messagesevent.origin
: Address to which the message is sentevent.data
: Message content
-
7. Nginx proxy is cross-domain
1, nginx configuration to resolve iconfont cross-domain
Browser cross-domain access js, CSS, and img conventional static resources are the same-origin policy permission, but iconfont font file (eot | otf | the vera.ttf | woff | SVG) exception, at this time in nginx server to add the following configuration static resources.
location / {
add_header Access-Control-Allow-Origin *;
}Copy the code
2. Nginx reverse proxy interfaces cross domains
Cross-domain principle: The same Origin policy is a security policy of the browser, not a part of the HTTP protocol. The server invokes the HTTP interface only using THE HTTP protocol, and does not execute JS scripts. There is no need for the same origin policy, so there is no crossing problem.
Nginx configure a proxy server (domain name and domain1 the same, different port) as a jumper, reverse proxy access to domain2 interface, and can incidentally modify the cookie in the domain information, convenient for the current domain cookie writing, cross-domain login.
Nginx configuration:
# proxy server
server {
listen 81;
server_name www.domain1.com;
location / {
proxy_pass http://www.domain2.com:8080; # Reverse proxy
proxy_cookie_domain www.domain2.com www.domain1.com; # change the domain name in cookie
index index.html index.htm;
# When accessing Nignx using middleware proxy interfaces such as Webpack-dev-server, there is no browser participation, so there is no source restriction, the following cross-domain configuration can not be enabled
add_header Access-Control-Allow-Origin http://www.domain1.com; # If the current end is cross-domain only without cookies, the value can be *
add_header Access-Control-Allow-Credentials true; }}Copy the code
1.) Front-end code examples:
var xhr = new XMLHttpRequest(); // Front-end switch: whether the browser reads and writes cookies xhr.withCredentials =true; // Access the proxy server xhr.open('get'.'http://www.domain1.com:81/?user=admin'.true);
xhr.send();Copy the code
2.) Nodejs
var http = require('http');
var server = http.createServer();
var qs = require('querystring');
server.on('request'.function(req, res) { var params = qs.parse(req.url.substring(2)); // Write cookie res.writeHead(200, {'Set-Cookie': 'l=a123456; Path=/; Domain=www.domain2.com; HttpOnly'// HttpOnly: script cannot read}); res.write(JSON.stringify(params)); res.end(); }); server.listen('8080');
console.log('Server is running at port 8080... ');Copy the code
8.WebSocket
WebSocket Protocol is a new protocol for HTML5. It implements full duplex communication between browser and server, and allows cross-domain communication. It is a good implementation of server push technology.
WebSocket is a communication protocol that is used
ws://
(unencrypted) and
wss://
(encryption) as a protocol prefix. This protocol does not enforce the same origin policy and can be used for cross-source communication as long as the server supports it.
The native WebSocket API is not very convenient to use, you can use socket. IO, which well encapsulates the WebSocket interface, provides a simpler, flexible interface, but also provides backward compatibility for browsers that do not support WebSocket. This is not installed because it is emulated using WebSocket
Here is an example of a WebSocket request header sent by the browser (from Wikipedia).
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
In the code above, one of the fields is Origin, indicating the Origin of the request, i.e. the domain name from which it originated.
It is because of the Origin field that WebSocket does not implement the same Origin policy. Because the server can determine whether to allow the communication based on this field. If the domain name is whitelisted, the server responds as follows.
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk= Sec-WebSocket-Protocol: chatCopy the code
1.) Front-end code:
// socket. IO can be used concurrentlylet socket = new WebSocket('ws://localhost:3000') socket.onopen = function (params) { socket.send('Front-end sending information'); } socket.onmessage = function (e) { console.log(e.data); }Copy the code
2.) Nodejs socket background: need to install the module WS
let express = require('express');let app = express();let Websocket = require('ws');letwss = new Websocket.Server({port:3000}); wss.on('connection'.function (ws) { ws.on('message'.function (data) { console.log(data); ws.send('Send websocket message from server'); })});Copy the code
9. Nodejs middleware proxy across domains
Node middleware implements cross-domain proxy, which is roughly the same as nginx. It starts a proxy server to forward data. It can also modify the domain name in the cookie in the response header by setting the cookieDomainRewrite parameter to implement cookie writing in the current domain, facilitating interface login authentication.
1. Cross-domain of non-VUE framework (twice cross-domain)
Build a proxy server with Node + Express + HTTP-proxy-middleware.
1.) Front-end code examples:
var xhr = new XMLHttpRequest(); // Front-end switch: whether the browser reads and writes cookies xhr.withCredentials =true; // Access http-proxy-middleware proxy server xhr.open('get'.'http://www.domain1.com:3000/login?user=admin'.true);
xhr.send();Copy the code
2.) Middleware server
var express = require('express');
var proxy = require('http-proxy-middleware');
var app = express();
app.use('/', proxy({// proxy cross-domain target interface target:'http://www.domain2.com:8080',
changeOrigin: true// Modify the response header to cross-domain and allow cookie onProxyRes:function(proxyRes, req, res) {
res.header('Access-Control-Allow-Origin'.'http://www.domain1.com');
res.header('Access-Control-Allow-Credentials'.'true'); }, // Modify the cookie domain name in the response message cookieDomainRewrite:'www.domain1.com'/ / can befalse})); app.listen(3000); console.log('Proxy server is listen at port 3000... ');Copy the code
3. Nginx: Nginx
2. Cross-domain of VUE framework (once cross-domain)
Cross domain using node + Webpack + webpack-dev-server agent interface. In the development environment, since the Vue rendering service and the interface proxy service are the same as Webpack-dev-server, there is no need to set headers cross-domain information between the page and proxy interface.
Webpack.config.js part configuration:
module.exports = {
entry: {},
module: {},
...
devServer: {
historyApiFallback: true,
proxy: [{
context: '/login',
target: 'http://www.domain2.com:8080', // Proxy cross-domain destination interface changeOrigin:true,
secure: false// Use cookieDomainRewrite when brokering an error for some HTTPS service:'www.domain1.com'/ / can befalse}], noInfo:true}}Copy the code