目的:浏览器为了安全而做出的限制策略。防止人随意篡改数据或者抓取数据。 浏览器请求必须遵循同源策略
同源策略 :同域名 同端口 同协议。
值得一提的是:同源策略导致的跨域是浏览器单方面拒绝响应数据,服务器端是处理完毕并做出了响应的。
如何解决跨域的问题?
CORS
服务器设置,前端直接调用。说明:后台允许前端某个站点进行访问。由服务器解决, 添加 cors 功能模块.
实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。
服务器设置Access-Control-Allow-Origin HTTP响应头之后,浏览器将会允许跨域请求。
jsonP跨域
适配,后台配合。前后端同时改造。利用 script 脚本的 src 不受同源策略限制的特点
script 标签 src 属性中的链 接却可以访问跨域的 js 脚本,利用这个特性,服务端不再返回 JSON 格式的数据,而是 返回一段调用某个函数的 js 代码,在 src 中进行了调用,这样实现了跨域。
JSON 只支持get,因为 script 标签只能使用 get 请求; JSONP 需要后端配合返回指定格式的数据。
前端需要下载jsonP插件: npm i jsonp --save-dev
接口代理
所谓代理就是:本该以我的名义做的事,现在请你去做。
代理的本质就是把自己的请求交给不受跨域限制的三方代理服务器,来规避同源策略
使用代理前 客户端的请求会直接发送到服务器 =》 然后服务器处理完毕响应客户端 =》 客户端检测是否同源 =》 发现不同源,啪,报错。 游戏结束
使用代理后
自己写一套nodejs的中间层
通过这个中间层去请求,比如说猫眼 (这里不会跨域)
前端代码再去请求这个中间层 (这里会跨域,但是可以解决)
原理:客户端向中间层发送请求,中间层又向后端发送请求,后端将数据返回给中间层,中间层再把数据返回给前端。
中间层如何操作
以请求猫眼电影如下地址为例:
http://m.maoyan.com/ajax/movieOnInfoList?token=&optimus_uuid=3AB8F27070A711EAB5F6EFED118239404C0B76B745824C469A76587DC457FAA1&optimus_risk_level=71&optimus_code=10
- 使用 nodejs 启动一个代理服务
- 下载引入http-proxy-middleware这样一个中间件
// 1. 引入 express
const express = require("express");
// 2. 引入 http-proxy-middleware 。并结构出它里面的 createProxyMiddleware 这个函数
const { createProxyMiddleware } = require("http-proxy-middleware");
// 3. 生成 express 实例
const app = express();
app.use((req, res, next) => {
res.set({
"Access-Control-Allow-Origin": "*"
});
next();
});
// 4. 调用代理中间件,确定一个前缀
app.use(
"/api",
createProxyMiddleware({
// 配置选项
// 目标地址, 只需要协议和主机。路径什么的不要
target: "http://m.maoyan.com",
// 路径重写
pathRewrite: {
"^/api": ""
},
changeOrigin: true
})
);
// end 监听端口
app.listen(3000, () => {
console.log("代理服务启动成功");
});
`//详解:
// 前端服务:http://localhost:8080
// 代理服务:http://localhost:3000
// 目标服务:http://m.maoyan.com
// 前端服务 -> 代理服务 -> 目标服务
http://localhost:8080 -> http://localhost:3000/api/ajax/movieOnInfoList?token=&optimus_uuid=3AB8F27070A711EAB5F6EFED118239404C0B76B745824C469A76587DC457FAA1&optimus_risk_level=71&optimus_code=10 -> http://m.maoyan.com/api/ajax/movieOnInfoList?token=&optimus_uuid=3AB8F27070A711EAB5F6EFED118239404C0B76B745824C469A76587DC457FAA1&optimus_risk_level=71&optimus_code=10
// 上述流程中,目标服务是不需要 /api 这个前缀的
// 这时还需要配置一个代理的路径重写规则 pathRewrite
// 前端服务 -> 代理服务 -> 目标服务
// http://localhost:8080 -> http://localhost:3000/api/ajax/movieOnInfoList?token=&optimus_uuid=3AB8F27070A711EAB5F6EFED118239404C0B76B745824C469A76587DC457FAA1&optimus_risk_level=71&optimus_code=10 -> http://m.maoyan.com/ajax/movieOnInfoList?token=&optimus_uuid=3AB8F27070A711EAB5F6EFED118239404C0B76B745824C469A76587DC457FAA1&optimus_risk_level=71&optimus_code=10
`
http://localhost:8080 -> http://localhost:3000/api/ajax/movieOnInfoList 是跨域的,但是进过 "Access-Control-Allow-Origin": "*"处理所以就不跨域了。/api直接进入m.maoyan.com 。目标服务是不需要 /api 这个前缀的,这时还需要配置一个代理的路径重写规则pathRewrite。