1. 跨域是什么: ajax地址 和 页面地址 不同源

  1. 浏览器使用ajax时, 如果请求接口地址和当前打开页面地址不同源, 称为跨域
  2. ajax地址: 跨域只会出现在ajax请求中, 其他的请求没有跨域
  3. 页面地址: location.href地址栏
  4. 不同源: 浏览器同源策略: 协议名、端口号、主机ip都一致

当页面发生跨域, 就会产生一个固定格式的报错

只要是跨域, 就一定会出现下面这种格式的报错, 但这种格式报错原因有很多, 比如基地址错误、服务器内部问题、跨度都有可能出现这种错误

Access to XMLHttpRequest at ‘ajax请求网址’ from origin ‘页面网址’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

2. 同源策略是一种安全策略

  1. 当使用ajax请求地址时, 与当前页面地址不一致时, 浏览器会认为给不同服务器发送了请求, 可能导致数据泄露, 因此会拒绝接收服务器的数据
  2. 跨域: 服务器可以收到请求, 也响应了请求, 但响应的数据被浏览器拒收了
  3. 出于安全考虑, 浏览器不允许页面向不同源的接口请求数据, 因为如果接口和网页不同源, 浏览器认为是2个不同的 服务器, 关于同源策略点击

分析以下有没有跨域:

  1. 页面地址: http://127.0.0.1:3000
  2. http://127.0.0.1:3000/list 同源
  3. http://127.0.0.1:5000 不同源 端口号不一样
  4. https://127.0.0.1:3000 不同源 协议名不一致
  5. http://localhost:3000 不同源 ip不一致

3. 如何解决跨域?

1. CORS技术: 后台设置允许跨域的响应头

  1. 应用场景: 前提是后台是自己的, 更多关于CORS
1
2
3
// 服务器在返回响应报文时, 在响应头中设置一个允许的header
res.setHeader('Access-Control-Allow-Origin', '*')
// 参数: 1.响应头名字 2.响应头值 *为所有网站都可以

2. 代理服务器

  1. 代理服务器: 用于帮你转发请求的服务器, 相当于中介代理
  2. 跨域只对浏览器ajax有限制, 对nodejs没有限制
  3. 使用代理转发请求-axios库: 既可在浏览器使用,也可在服务器使用,它会自动判断当前代码运行环境
  4. 将数据返回给浏览器 (服务器不能直接给对象, 需转换为json)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
let http = require('http')
let axios = require('axios') // 导入axios

let app = http.createServer(async (req, res) => {
// 1. 设置允许跨域响应头
// 参数: 1.响应头名字 2.响应头值 *为所有网站都可以
res.setHeader('Access-Control-Allow-Origin', '*')
res.writeHead(200, {
'Content-Type': 'text/html;charset=utf-8'
})
if (req.url == '/') {
res.end('请求成功')
} else if (req.url == '/a') {
// 2. 使用axios库: 既可在浏览器使用,也可在服务器使用,它会自动判断当前代码运行环境
let res1 = await axios.get('http://c.m.163.com/nc/article/headline/T1348647853363/0-40.html')
console.log(res1)
// 3. 将数据返回给浏览器 (服务器不能直接给对象, 需转换为json)
res.end(JSON.stringify(res1.data))
} else {
res.end('404 not found')
}
})

app.listen('3000', '', () => {
console.log('开启成功')
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
document.querySelector('.btn1').addEventListener('click', function () {
// 给我们自己nodejs服务器发请求
let xhr = new XMLHttpRequest()
xhr.open('get', 'http://127.0.0.1:3000/')
xhr.send()
xhr.onload = function () {
console.log(xhr.responseText)
}
})

document.querySelector('.btn2').addEventListener('click', function () {
//给别人的网易云服务器发请求
let xhr = new XMLHttpRequest()
// xhr.open('get', 'http://c.m.163.com/nc/article/headline/T1348647853363/0-40.html')
// 使用代理服务器解决跨域
xhr.open('get', 'http://127.0.0.1:3000/a')
xhr.send()
xhr.onload = function () {
console.log(xhr.responseText)
}
})

3. 代理服务器流程

  1. 页面 给 代理服务器 发请求
  2. 代理服务器 给 目标服务器 发请求
  3. 目标服务器 把 数据响应给代理服务器
  4. 代理服务器 最后把 数据响应给页面

3. JSONP: 曾经的跨域杀手, 专治各种跨域问题, 现在慢慢淡出历史舞台