当前位置:网站首页>Cross domain, CORS, jsonp
Cross domain, CORS, jsonp
2022-06-30 02:55:00 【Cherish time, Xiao Li】
Cross domain 、CORS、JSONP( Interview required )
ajax and Promise Is a cross-domain problem
Cross domain general 2 Kind of plan JSONP and CORS
Cross domain
The interaction between the front end and the back end .
Key knowledge
1. The same-origin policy A feature limitation deliberately designed by browsers
2.CORS One way to break the browser restrictions
3.JSONP IE The compromise of the times
One . The same-origin policy
1. The definition of homology
Source
Console input window.origin or location.origin You can get the current source
Source = agreement + domain name + Port number
If two url The agreement 、 domain name 、 The port numbers are exactly the same , So these two url It's homologous .
give an example
https://qq.com、https://www.baidu.com Different sources
https://baidu.com、https://www.baidu.com Different sources
Identical is homology
2. Homology policy definition
Browser rules
If JS Run at source A You can only get the source A The data of , Cannot get source B The data of , namely Cross domain is not allowed .
give an example ( Omit http agreement )
hypothesis diaoyu.com/index.html Refer to the cdn.com/1.js
Then say 1.js Run at source diaoyu.com in . Pay attention to this one cdn.com No problem , although 1.js From it download
therefore 1.js You can only get diaoyu.com The data of
1.js You can only access the data of this domain name in which domain name you are running
This is the function of the browser , Browsers are designed to do this .
The purpose of the browser is to Protect user privacy .
How to protect ?( Suppose there is no homology strategy , be-all js You can access the data of all websites )
With QQ Space as an example
From https://user.qzone.qq.com
hypothesis , The current user has logged in ( The login information is saved in the browser Cookie in ), Now you can view your friends list .
Friend information is through Ajax request /friends.json Get a list of friends
hypothesis ,Ajax request /friends.json You can get the user's friend list
So far, it's normal
Here comes the hacker
Suppose your goddess ( hackers ) Share https://qzone-qq.com Here you are. , It's actually a phishing website .
You click on this page , This page also requests your friends list
https://user.qzone.qq.com/friends.json
Excuse me, , Is your friend list stolen by hackers ? Yes
The root of the problem
The first 1 This is a normal request , The first 2 The second is the request of the hacker . There is little difference except referrer
Console XHR yes XMLHttpRequest The abbreviation for ajax Abbreviation
The same-origin policy : Between pages from different sources , No access to each other's data
practice Complete code
do 2 A website to demonstrate
step
1. establish 2 A catalog qq-com and diaoyu-com
qq-com New directory server.js, simulation QQ Space
diaoyu-com New directory server.js, Simulate the bad guys' space
Open the... First 1 A catalog , And then I will 2 Add directories to the workspace
install :yarn global add node-dev
Use :node-dev server.js 8888 //qq-com
node-dev server.js 9999 //diaoyu-com
2.qq-com
/index.html It's the home page
/qq.js yes JS Script files
/friends.json Is simulated friend data
Port listening is 8888, visit http://127.0.0.1:8888
Operation steps
To write path=’/index.html’ route , Then build index.html.server.js Will read index.html.
To write path === '/qq.js’ route , Then build qq.js.server.js Will read qq.js.
To write path === '/friends.json’ route , Then build friends.json.server.js Will read friends.json.
Knowledge point :fs file 、fs modular - Ruan Yifeng recommend Net channel
Node.js The file system is encapsulated in fs Module , It provides access to files 、 write in 、 renamed 、 Delete 、 Traverse the directory 、 Links, etc. POSIX File system operations
fs Basic use of modules :
var fs = require('fs') // quote fs
response.write(fs.readFileSync('./public/index.html'))
3.diaoyu-com
The operation steps are the same as above
/index.html It's the home page
/diaoyu.js yes JS Script files
Add :diaoyu-com There is no need to write a route /friends.json
Port listening is 9999, visit http://127.0.0.1:9999
4. Give Way qq.js success Visit your own json(friends.json) data
Give Way diaoyu.js Can't succeed visit qq Of json
The domain name is different ? Set local domain name mapping , modify hosts
Give Way qq.com Mapping to 127.0.0.1, You can access http://qq.com:8888/index.html 了
Give Way diaoyu.com Mapping to 127.0.0.1, You can access http://diaoyu.com:9999/index.html 了
Cross domain AJAX
Demo cross domain blocked
1.qq-com
First index.html application js<script src="qq.js"></script>
then qq.js Send a request
const request = new XMLHttpRequest()
request.open('GET', './friends.json')
request.onreadystatechange = () => {
if (request.readyState === 4 && request.status === 200) {
console.log(request.response)
}
}
request.send()
2.diaoyu-com
Ibid
First index.html application js<script src="./diaoyu.js"></script>
then qq.js Send a request
const request = new XMLHttpRequest()
request.open('GET', 'http://qq.com:8888/friends.json')// request qq.com Of json
request.onreadystatechange = () => {
if (request.readyState === 4 && request.status === 200) {
console.log(request.response)
}
}
request.send()
diaoyu-com Unwanted /friends.json route
Tips : From source “http://diaoyu.com:9999” visit “http://qq.com:8888/friends.json” Of XMLHttp The request has been CORS Policy prevents : The requested resource does not exist “ visit - control - Allow sources ” head .
response Can't get qq.com The data of , because CORS Strategy prevents .
This is cross domain , Cross domain will be blocked . Browsers restrict cross domain , Deliberately not giving data . Browser needs CORS.
Other questions
1. Why? a.qq.com visit qq.com It's also cross domain ?
Because different companies have shared domain names in history .a.qq.com and qq.com Not necessarily the same website . Browser caution , Think this is a different source .
2. Why are different ports cross domain ?
The reason as above . Once because the server was more expensive , Many companies share the same server , This leads to one port for one company , The data of the two companies are not shared . Remember that the strength of the safety chain depends on the weakest link , Any safety related issues should be treated with caution .
3. Why two websites IP It's the same , It's also cross domain ?
The reason as above .IP All the same instructions are on the same server . In the early days, servers were very expensive , So a server hung up 20 It is possible to have pages from different websites . So because IP Can share , In fact, they are different companies .
4. Why can I use... Across domains CSS、JS、 picture ?
Interview questions
The same origin policy restricts data access , We quote CSS、JS、 In the picture , In fact, I don't know its content , We are just quoting . It can be referenced but not read . If you don't believe me, I ask you , You can see CSS Of the 1 What is a character ?
Although it is theoretically required that different websites cannot share data , Cross domain is not allowed , But in the actual work or interview, I often ask How to share data across domains .
Realize cross domain 2 Methods
Method 1 :CORS Cross-domain resource sharing
The root cause of the problem
By default, browsers cannot access data from different sources .
however qq.com and diaoyu.com In fact, they are all my websites , I just want two websites to visit each other , Why does the browser block .
ok , use CORS
The browser says , If you want to share data , It needs to be declared in advance !
How to declare ?
The browser says ,qq.com Write... In the response header diaoyu.com You can visit
Set the response header Access-Control-Allow-Origin: http://foo.example
CORS file CORS There are simple requests and complex requests. See the document for details
Sample code
else if (path === '/friends.json') {
response.statusCode = 200
response.setHeader('Content-Type', 'text/json;charset=utf-8')
response.setHeader('Access-Control-Allow-Origin', 'http://diaoyu.com:9999')
response.write(fs.readFileSync('./public/friends.json'))
response.end()
}


If there is 2 Every website wants to request qq.com Well ?
Ideas : Come to a website and read a website , Not this 2 All websites are written on it .
console.log(request.headers[‘referer’])
Record the website you are currently requesting , And then re record to Access-Control-Allow-Origin Back
️ Be careful :IE I won't support it CORS, To be compatible IE You can only use the second 2 Methods
Method 2 :JSONP( compatible IE)
JSONP and JSON It's nothing to do with half a cent
Remember that we can quote anything JS
Although we can't visit qq.com:8888/friends.json, But we can quote qq.com:8888friends.js ah !
What's the point ?
JS It's not data
We let JS If only the data were not included , Write data to js In the document
qq Create a that contains data js,diaoyu.com visit qq.com
step
1.qq.com Write data to /friends.js
qq New file friends.js, Code
{ { data } } // placeholder
2. Background write route
Get it backstage js Content 、 get data json, Fill in the data in js Content . And then back to the browser .
else if (path === '/friends.js') {
response.statusCode = 200
response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
const string = fs.readFileSync('./public/friends.js').toString()
const data = fs.readFileSync('./public/friends.json').toString()
// Default is not string want toString
const string2 = string.replace('{
{data}}', data)
// hold data Plug into the string in . Using data data Hold the seat {
{data}} Replace
response.write(string2)
response.end()
}
Add :js It is illegal to only have data in the file. You need to assign values
window.xxx = { { data } }
3.diaoyu.com use script Label reference /friends.js,js Dynamic reference
diaoyu.js
const script = document.createElement('script')
script.src = 'http://qq.com:8888/friends.js'
document.body.appendChild(script)

How do you determine whether the data is available ? monitor script Of onload event
const script = document.createElement('script')
script.src = 'http://qq.com:8888/friends.js'
script.onload = () => {
console.log(window.xxx)
}
document.body.appendChild(script)
4.js It is illegal to only have data in the file. You need to assign values , however xxx May be occupied , You can use functions
//window.xxx={
{data}}
window.xxx({
{ data }})
diaoyu.js
No more monitoring onload 了 . Because as long as the execution is successful, the function can be called window.xxx 了
window.xxx = (data) => {
console.log(data)
}
const script = document.createElement('script')
script.src = 'http://qq.com:8888/friends.js'
document.body.appendChild(script)

Callback : I define a function to be called by others , Give me a data when others adjust it .
window.xxx The essence is a callback
I define but do not call , Waiting for the qq.com Script for js file (friends.js) To call . The data will be used as the first 1 Pass me parameters .
JSONP referer Check restricted visitors
CORS You can specify who visitors ,JSONP There is no way to specify , that JSONP Of js Not all websites can be used ?
Yes , however JSONP You can do it referer Check restricted visitors .
else if (path === '/friends.js') {
if (request.headers['referer'].indexOf('http://diaoyu.com:9999') === 0) {
response.statusCode = 200
response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
//console.log(request.headers['referer']) //http://diaoyu.com:9999
const string = fs.readFileSync('./public/friends.js').toString()
const data = fs.readFileSync('./public/friends.json').toString()
const string2 = string.replace('{
{ data }}', data)
response.write(string2)
response.end()
} else {
response.statusCode = 404
response.end()
}
}
indexOf()
Even so, there will still be security risks , Once the website I trust is captured (diaoyu.com), that qq.com It's over .
There are more stringent restrictions that will be discussed later ( involve Cookie、Token)
Optimize JSONP
One .xxx Can we not write dead ?
If I have multiple interfaces , except " The friends list ", also " Recent visitors " etc. , This obviously does not meet our needs . The name doesn't matter , as long as diaoyu.com Defined function name and qq.com/friends.js The name of the executed function is the same . Then pass your name to /friends.js
1. Ideas : Automatic generation
const random = Math.random()
//console.log(random) 0~1 Decimals of , be-all key Can be a string , As long as it's a string
window[random] = (data) => {
//window['0.023216364']= function
console.log(data)
}
2. How to give random numbers to the background ? Query parameters ?functionName
diapyu.js
script.src = `http://qq.com:8888/friends.js?functionName=${
random}`
How to render it to js in ?
qq.com
else if (path === '/friends.js') {
if (request.headers['referer'].indexOf('http://diaoyu.com:9999') === 0) {
...
console.log(query.functionName) //query?
}
}

Add url.parse
var parsedUrl = url.parse(request.url, true)
var query = parsedUrl.query
grammar : The first 2 Parameters ( It saves ) Pass in a Boolean value , The default is false, by true when , Back to url In the object ,query The attribute of is an object .
url.parse("http://user:[email protected]:8080/p/a/t/h?query=string#hash",true);
Return value :
{
protocol: 'http:',
slashes: true,
auth: 'user:pass',
host: 'host.com:8080',
port: '8080',
hostname: 'host.com',
hash: '#hash',
search: '?query=string',
query: {
query: 'string' },
pathname: '/p/a/t/h',
path: '/p/a/t/h?query=string',
href: 'http://user:[email protected]:8080/p/a/t/h?query=string#hash'
}
Will be the first 2 Parameters are set to true when ,query The attribute is “ name / value ” For the collection of , namely json Format .
Insert a random number into a string
friends.js
window['{
{xxx}}']({
{ data }})
then { {xxx}} Replace with random numbers
const string2=string.replace('{
{ data }}', data).replace('{
{xxx}}',query.functionName)
It can be more complicated : Add a prefix
const random = 'diaoyuJSONPCallbackName' + Math.random()
Two . Delete after execution <script> label
Every time a request is made, an additional <script> label , The page will also become bloated .
const random = 'diaoyuJSONPCallbackName' + Math.random()
console.log(random)
window[random] = (data) => {
console.log(data)
}
const script = document.createElement('script')
script.src = `http://qq.com:8888/friends.js?functionName=${random}`
script.onload = () => { // Delete <script> label
script.remove()
}
document.body.appendChild(script)
As long as it's done ,<script> It's useless. , You can delete
3、 ... and . encapsulation jsonp()
Encapsulated into jsonp(‘url’).then(f1,f2)
function jsonp(url) {
return new Promise((resolve, reject) => {
const random = 'diaoyuJSONPCallbackName' + Math.random()
window[random] = (data) => {// A successful call resolve
resolve(data)
}
const script = document.createElement('script')
//script.src = `${url}?functionName=${random}`
script.src = `${url}?callback=${random}`
script.onload = () => {
script.remove()
}
script.onerror = () => {// Failed call reject
reject()
}
document.body.appendChild(script)
})
}
jsonp('http://qq.com:8888/friends.js').then((data) => {
console.log(data)
})
jsonp And ajax The weakness of contrast ,jsonp Only success can be known / Failure , Unable to get the status code .
️ Be careful :jsonp Contract query parameters cannot be called functionName It should be called callback?callback
Four . Delete file friends.js
friends.js Of window['{ {xxx}}']({ { data }}) This code can be written directly in the background .
//const string = fs.readFileSync('./public/friends.js').toString()
const string = `window['{
{xxx}}']({
{ data }})`
JSONP To create a <script> request js,js Bring the data to me
There are other cross domain schemes that you can search by yourself
Interview questions
JSONP What is it? ?
1. Cross domain, because the current browser does not support CORS, So we must use another way to realize cross domain .
So we asked for one js file , This js The file will execute a callback , There is our data in the callback .
Questioning , What is the name of your callback ?
Callback names can be generated randomly 1 A random number , We put the name after callback Pass the parameters to the background , The background will return this function to us again and execute .
2.JSONP advantage :(1) compatible IE (2) You can cross domains
3.JSONP shortcoming :
(1) Because it is <script> label , So it can't read ajax So precise state . Status code 、 The response header doesn't know , Only know success and failure .
(2) Because it is <script> Labels can only be sent get request ,JSONP I won't support it post.
边栏推荐
- High paid programmers & interview questions series 63: talk about the differences between sleep (), yield (), join (), and wait ()
- [dry goods sharing] the latest WHQL logo certification application process
- HTA入门基础教程 | VBS脚本的GUI界面 HTA简明教程 ,附带完整历程及界面美化
- SQLite使用
- What is the difference between a layer 3 switch and a layer 2 switch
- Jupyter notebook displays a collection of K-line graphs
- Global and Chinese market of subscription revenue management software 2022-2028: Research Report on technology, participants, trends, market size and share
- 公司电脑强制休眠的3种解决方案
- Série de tutoriels cmake - 02 - génération de binaires à l'aide du Code cmake
- 中断操作:AbortController学习笔记
猜你喜欢

IDEA 远程调试 Remote JVM Debug

Unity3d ugui force refresh of layout components
![[dry goods sharing] the latest WHQL logo certification application process](/img/c3/37277572c70b0af944e594f0965a6c.png)
[dry goods sharing] the latest WHQL logo certification application process

Mysql提取表字段中的字符串

Idea remote debugging remote JVM debug

Five cheapest wildcard SSL certificate brands

重磅来袭--UE5的开源数字孪生解决方案

IBM WebSphere channel connectivity setup and testing

Unity3D UGUI强制刷新Layout(布局)组件

Unity timeline data binding
随机推荐
多卡服务器使用
IBM WebSphere channel connectivity setup and testing
Steam elements hidden in science and Technology Education
【直播笔记0629】 并发编程二:锁
Call collections Sort() method, compare two person objects (by age ratio first, and by name ratio for the same age), and pass lambda expression as a parameter.
Time complexity analysis
中断操作:AbortController学习笔记
Xunwei enzhipu ITop - imx6 Development Platform
How to prevent phishing emails? S/mime mail certificate
Precautions for purchasing wildcard SSL certificate
How can redis+aop customize annotations to achieve flow restriction
Customize the buttons of jvxetable and the usage of $set under notes
Cmake tutorial series-01-minimum configuration example
CMake教程系列-05-选项及变量
Pytoch learning (II)
Five cheapest wildcard SSL certificate brands
JvxeTable子表记录加载完毕事件
Raki's notes on reading paper: Leveraging type descriptions for zero shot named entity recognition and classification
身份证号的严谨判断精确到队后一位
How does native JS generate Jiugong lattice