跨域产生原因
跨域产生的原因主要是同源策略,同源策略是浏览器提供的一种安全机制,可以防止跨站脚本攻击。
也就是A网站请求B网站的资源,是否能够使用的问题
同源策略:协议(http/https)、域名/IP地址、端口号,一致则同源,代表是同一个网站,资源共享
有一项不同既不同源
有一项不同既不同源,代表是两个网站,此时资源不共享
为什么产生跨域
首先前后端部署在同一个服务下,不会存在跨域,但是当下,最流行的就是前后分离
项目,也就是前端项目
和后端接口
并不在一个域名之下,那么前端项目访问后端接口必然存在跨域
的行为.
解决方案
JSONP
利用的不是xhr请求, 利用的script标签的src可以跨域, 请求接口资源,同时携带callback回调函数名字, 将数据传给回调函数, 解决get不能解决post
function jsonp(url, callback) {
const script = document.createElement('script');
script.src = url + '?callback=' + callback;
document.body.appendChild(script);
}
function handleData(data) {
console.log(data);
}
jsonp('http://example.com/data', 'handleData');
JSONP 的优点是:
- 跨域支持,可以在不同的域名之间进行数据交互。
- 兼容性好,可以在老旧浏览器中使用。
JSONP 的缺点是:
- 安全问题,因为服务器返回的数据会被直接执行,可能存在 XSS 攻击等安全风险。
- 只支持 GET 请求,不能使用 POST 等其他请求方式。
- 难以维护,因为请求和回调函数之间的关系不明显,代码可读性较差。
CORS
CORS(Cross-Origin Resource Sharing,跨域资源共享)是一种跨域解决方案,它通过在 HTTP 头部添加特定的字段,来告诉浏览器是否允许跨域请求,cors跨域分为简单请求和非简单请求的两种方式处理
简单请求的规则:
- 使用 GET、HEAD、POST 方法中的任意一种。
- Content-Type 是 application/x-www-form-urlencoded、multipart/form-data、text/plain 中的任意一种。
- 请求中没有使用自定义的头部字段。
如果请求满足以上条件,则为简单请求,否则为复杂请求
简单请求cors跨域流程
在浏览器发出请求后,浏览器判断是简单请求还是复杂请求,如果是简单请求
- 会自动在请求头部加上 Origin 字段,表示该请求来自哪个域。
- 如果服务器允许该域的跨域请求,就在响应头部加上 Access-Control-Allow-Origin 字段,表示允许该域的跨域请求
- 浏览器正确处理响应。如果服务器不加上Access-Control-Allow-Origin字段,浏览器将无法读取响应数据。
复杂请求cors跨域流程
在浏览器发出请求后,浏览器判断是简单请求还是复杂请求,如果是复杂请求请求:
- 浏览器在发送跨域请求时,会先发送一个 OPTIONS 请求,该请求称为 Preflight Request。Preflight Request 的目的是向服务器确认当前跨域请求是否被允许。Preflight Request 请求头中会包含一个 Access-Control-Request-Method 字段,表示实际请求使用的 HTTP 方法。
- 服务器在接收到 Preflight Request 后,会检查请求头部中的 Origin 字段,判断当前跨域请求是否被允许。如果被允许,服务器会在响应头部中添加一些 CORS 相关的字段,如 Access-Control-Allow-Origin、Access-Control-Allow-Methods、Access-Control-Allow-Headers 等。
- 浏览器接收到服务器返回的响应后,会检查响应头部中的 CORS 相关字段是否符合要求,如果符合要求,就会发送实际的跨域请求。实际的跨域请求与普通请求一样,只不过在请求头部中多了一个 Origin 字段。
服务器代理
通过在vue-cli脚手架中配置proxy进行跨域处理
代理服务器的原理流程:
- 客户端发起请求至本地服务器
- 本地服务器做代理,请求目标服务器,由于服务器和服务器之间不存在跨域的问题,所以可以正常请求响应
- 目标服务器将数据响应至本地服务
- 本地服务器将数据响应至客户端
具体配置:
devServer: {
proxy: {
'/api': {
target: '接口url地址',
pathRewrite: '重写'
}
}
}
但是,vue-cli的跨域只能解决开发期间的跨域问题,项目上线跨域问题需要配置nginx
nginx代理
在nginx服务器nginx.conf配置文件
server {
listen 8083;# 监听的端口
server_name localhost; #监听的主机名 也可以是域名或者ip地址
location ~ /api/ {
proxy_pass http://localhost:8084;
}
location ~ /prod/ {
proxy_pass http://localhost:8085;
}
}