跨域解决方案
1. 浏览器的同源策略
浏览器为了确保资源安全,而遵循的一种策略。
- 源 = 协议 + 域名 + 端口号
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
响应头,来明确表达允许某个源发起跨域请求,随后浏览器在校验时,直接通过。
- 假设本地的http://127.0.0.1:8080请求服务器中http://127.0.0.1:8081/getUsers的接口
在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):GET 、HEAD 、 POST | 1. 不是简单请求,就是复杂请求 |
请求头字段要符合《CORS安全规范》 只要不手动修改请求头,一般都能符合该规范。 | 2.复杂请求会自动发送预检请求 |
请求头的Content-Type 的值只能是以下三种:- text/plain - multipart/form-data - application/x-www-form-urlencoded |
关于预检请求:
- **发送时机:**预检请求在实际之前发出,是由的。
- **主要作用:**用于向服务器确认是否允许接下来的跨域请求。
- **基本流程:**先发起一个
OPTIONS
请求,如果预检,实际的跨域请求。 - **请求头内容:**一个
OPTIONS
预检请求,通常会包含如下
请求头 | 含义 |
---|---|
Origin | 发起请求的源文件 |
Access-Control-Request-Method | 实际请求的HTTP方法 |
Access-Control-Request-Headers | 实际请求中使用的自定义头(如果有的话) |
4.4 CORS解决跨域
- **第一步:**服务器先浏览器的,服务器需要返回如下
请求头 | 含义 |
---|---|
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()
})
- **第二步:**处理实际的跨域请求(与处理简单请求的跨域的方式相同)
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请求)
- JSONP概述:JSONP是利用了
<script>
标签可以跨域加载脚本,且不受严格限制的特性,可以说是程序员智慧的结晶,早期一些浏览器不支持CORS的时候,可以使用JSONP解决跨域 - 基本流程
- **第一步:**客户端创建一个
<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': ''
}
}))