CORS跨域 / Nodejs中间件代理跨域
跨域:指的是浏览器行为,正常情况下是成功的,只是同源策略不允许拿数据,所以会报错。
jsonp 方式跨域,主要的负担都由前端来承担,但是无法携带参数。
cors 方式跨域,主要的负担由后端来承担,看起来较为优雅。
CORS跨域
CORS是一个W3C标准,全称是"跨域资源共享"( Cross-origin resource sharing )。
它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了 AJAX 只能同源使用的限制。
实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨域通信。
跨域实现
准备两个后端服务器,均启动服务
- 前端ajax 申请
修改路由,指定访问资源地址
let xhr = new XMLHttpRequest();
xhr.open("post","http://localhost:4000/post",true); // 直接修改路由即可
xhr.onload = function(){
console.log(xhr.responseText);
let res = xhr.getAllResponseHeaders();
console.log(res)
}
xhr.send();
- 后端服务器 允许
允许非同源进行访问
router.post("/post", async ctx => {
console.log((ctx.request.body)) // 接收返回的数据
// 允许所有的端口访问 即允许跨域
// ctx.set("Access-Control-Allow-Origin","*");
// 1. 不安全 2. 不能设置允许携带凭证
// 允许指定的端口访问
ctx.set("Access-Control-Allow-Origin", "http://localhost:3000");
ctx.body = "端口号4000非同源"; // 测试数据
// 没有数据返回 post方式下 直接报错
})
简单请求
受到浏览器的同源策略影响,同源状态下,cookie等存储不受到限制
但是,跨域使用时则会受到影响。
请求方法是以下三种方法之一:
- HEAD
- GET
- POST
HTTP的头信息不超出以下几种字段:
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
前端页面准备
前端需要 获取 / 设置 信息,但需要后端来开启对应的权限
携带凭证 是指cookie为代表的存储方式
// 允许跨域请求携带凭证 (开启)
xhr.withCredentials = true;
// 指定跨域链接地址
xhr.open("post","http://localhost:4000/post",true);
// 设置请求头
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xhr.setRequestHeader("Content-type","application/json");
后端服务器准备
以前端为主,前端需要什么就开启相对应的设置
// 1 允许指定的端口访问 必须开启的设置
ctx.set("Access-Control-Allow-Origin", "http://localhost:3000");
// 2 允许获取头部信息(响应头部)
ctx.set("Access-Control-Expose-Headers", "Content-Type,Content-length,Date");
// 3 设置允许前端设置的请求方式(请求头部类型和数值)
ctx.set("Access-Control-Allow-Headers", "Content-Type,Content-Length,test");
// 4 设置允许前端发送请求的方式
ctx.set("Access-Control-Allow-Methods", "GET,POST,DELETE,HEAD,OPTIONS");
// 5 允许携带凭证
ctx.set("Access-Control-Allow-Credentials", true);
// 6 设置预检请求的缓存时间 两个位置都写
ctx.set("Access-Control-Max-Age", 36000 * 24);
非简单请求
非简单请求是那种对服务器有特殊要求的请求
比如请求方法是PUT或DELETE,或者Content-Type字段的类型是application/json。
非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。
在实际项目中我们的请求格式可能是 application/json 格式编码,或者使用自定义请求头都会触发 CORS 的预检请求。
后端服务器准备
开启预检请求,对应的服务
但是相对应的该有的服务,不能减少
// 处理预检请求 通用 所有的接口
router.options("/*", ctx => {
// 1 允许所有的端口访问 允许跨域
ctx.set("Access-Control-Allow-Origin", "http://localhost:3000");
// 2 允许获取头部信息(响应头部)
ctx.set("Access-Control-Expose-Headers", "Content-Type,Content-length,Date");
// 3 设置允许前端设置的请求方式(请求头部类型和数值)
ctx.set("Access-Control-Allow-Headers", "Content-Type,Content-Length,test");
// 4 设置允许前端发送请求的方式
ctx.set("Access-Control-Allow-Methods", "GET,POST,DELETE,HEAD,OPTIONS");
// 5 允许携带凭证 cookie只是其中之一
ctx.set("Access-Control-Allow-Credentials", true);
// 6 设置预检请求的缓存时间 两个位置都写
ctx.set("Access-Control-Max-Age", 36000 * 24);
console.log("有预检请求");
ctx.body = "响应中..."
})
Nodejs中间件代理跨域
利用 node.js 的中间件去处理跨域,类似于
将跨域请求交给第三方,第三方去访问指定的网络,获取数据然后返回
koa-server-http-proxy
记得下载及引用服务
自身所在的服务端开启相应的设置
相对应的数据 还是要在想要跨域的路由中才能获取到
- 自身后端设置
const koaServerHttpProxy = require("koa-server-http-proxy");
// 服务器端接口转发
app.use(koaServerHttpProxy("/api",{
target:"http://localhost:4000", // 跨域的指定地址
pathRewrite:{'^/api':''}, // 限定 跨域的条件: 以 api 开头
changeOrigin:true // 开启服务
}));
- 前端设置
let xhr = new XMLHttpRequest();
xhr.open("post","/api/Serverpost",true); // 与后端的设置需要一致 api
xhr.onload = function(){
console.log(xhr.responseText);
}
xhr.send();