Skip to content

跨域解决方案

1. 浏览器的同源策略

浏览器为了确保资源安全,而遵循的一种策略。

  • 源 = 协议 + 域名 + 端口号
源1源2是否同源
http://chenjinbo.cn/tubiao/https://chenjinbo.cn/tubiao/不同源(协议不同)
https://www.chenjinbo.cn/https://blog.chenjinbo.cn/不同源(二级域名不一致)
https://www.chenjinbo.cn:8080https://www.chenjinbo.cn:8081不同源(端口不一致)
https://www.chenjinbo.cn/tubiao/https://www.chenjinbo.cn/MyBlog/同源

2.跨域会受到哪些限制

  • 限制DOM访问
  • 限制Cooike访问
  • 限制Ajax获取数据

3. 跨域注意点

  • 跨域限制仅存在浏览器端,服务端不存在跨域限制
  • 即使跨域了,Ajax请求也可以正常发出,但响应数据不会交给浏览器
  • <link><script><img>...这些标签发出的请求也可能跨域,只不过浏览器对标签跨域不做严格限制,对开发不受影响。

4. CORS解决Ajax跨域问题

4.1 CORS概述

CORS全称:Cross-Origin Resource Sharing(跨域资源共享),是用于控制跨域请求的一套规范,服务器依照CORS规范,添加特定响应头来控制浏览器校验,大致规则如下:

  • 服务器明确表示请求,或,则浏览器校验
  • 服务器明确表示请求,则浏览器校验

**备注:**使用CORS解决跨域是最佳的解决方案,且需要要求服务器最好是""

4.2 CORS解决跨域

思路:服务器在给出响应时,通过添加Access-Control-Allow-Origin响应头,来明确表达允许某个源发起跨域请求,随后浏览器在校验时,直接通过。

在Ajax请求时候请求头有origin为:http://127.0.0.1:8080

在node中的express中使用

const express = require('express')
const app = express()
const users = [
	{ id: 'anbfg3', name: 'lisichun', age: 20 },
	{ id: 'anbfg2', name: 'shihuang', age: 12 },
	{ id: 'anbfg1', name: 'yefang', age: 18 },
]
app.get('/getUsers', (req, res) => {
	res.setHeader('Access-Control-Allow-Origin', 'http://127.0.0.1:8080')
	res.send(users)
})
app.listen(8081, () => {
	console.log('服务器已启动,在http://127.0.0.1:8081')
})

4.3 简单请求和复杂请求

CORS会把请求分为两类,分别是:①简单请求、②复杂请求

简单请求复杂请求
请求方法(method):GETHEADPOST1. 不是简单请求,就是复杂请求
请求头字段要符合《CORS安全规范》
只要不手动修改请求头,一般都能符合该规范。
2.复杂请求会自动发送预检请求
请求头的Content-Type的值只能是以下三种:
- text/plain
- multipart/form-data
- application/x-www-form-urlencoded

关于预检请求:

  1. **发送时机:**预检请求在实际之前发出,是由的。
  2. **主要作用:**用于向服务器确认是否允许接下来的跨域请求。
  3. **基本流程:**先发起一个OPTIONS请求,如果预检,实际的跨域请求。
  4. **请求头内容:**一个OPTIONS预检请求,通常会包含如下
请求头含义
Origin发起请求的源文件
Access-Control-Request-Method实际请求的HTTP方法
Access-Control-Request-Headers实际请求中使用的自定义头(如果有的话)

4.4 CORS解决跨域

  1. **第一步:**服务器先浏览器的,服务器需要返回如下
请求头含义
Access-Control-Allow-Origin允许的源
Access-Control-Allow-Methods允许的方法
Access-Control-Allow-Headers允许的自定义头
Access-Control-Max-Age预检请求的结果缓存时间(可选)

服务端代码:

// 处理预检请求
app.options('/getUsers', (req, res) => {
	// 设置允许的跨域请求源
	res.setHeaders('Access-Control-Allow-Origin', 'http://127.0.0.1:8080')
	// 设置允许的请求方法
	res.setHeaders('Access-Control-Allow-Methods', 'GET')
	// 设置允许的请求头
	res.setHeaders('Access-Control-Allow-Headers', 'name')
	// 设置预检请求的缓存时间(可选)
	res.setHeaders('Access-Control-Max-Age', 3600)
	// 发送响应
	res.send()
})
  1. **第二步:**处理实际的跨域请求(与处理简单请求的跨域的方式相同)

4.5 使用CORS库完成跨域配置

使用cors中间件

const cors = require('cors')

app.use(cors()) // 都允许

// 自定义配置
app.use(cors(
 origin: 'http://127.0.0.1:8080', // 允许的源
 methods: ['GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS'], // 允许的方法
 allowedHeaders:['name'], // 允许的自定义头
 exposedHeaders: ['age'], // 暴露的响应头
 optionsSuccessStatus: 200 // 预检请求成功的状态码
))

5. JSONP解决跨域问题(只能解决GET请求)

  1. JSONP概述:JSONP是利用了<script>标签可以跨域加载脚本,且不受严格限制的特性,可以说是程序员智慧的结晶,早期一些浏览器不支持CORS的时候,可以使用JSONP解决跨域
  2. 基本流程
    • **第一步:**客户端创建一个<script>标签,并且将其src属性设置为包含跨域请求的URL,同时准备一个回调函数,这个回调函数用于处理返回的数据。
    • **第二步:**服务端接收到请求后,将数据封装在回调函数中并返回。
    • **第三步:**客户端的回调函数被调用,数据以参数的形势传入回调函数。

6.配置代理解决跨域

6.1自己配置代理服务器

使用http-proxy-middleware

const { createProxyMiddleware }  = require('http-proxy-middleware')
app.use('/api', createProxyMiddleware({
  target: 'https://www.toutiao.com',
  changeOrigin: true,
  pathRewrite: {
  	'^api': ''
  }
}))

6.2使用Nginx搭建代理服务器

6.3借助脚手架搭建服务器