文章目录
1. 为什么会出现跨域?
- 跨域是一种约定,是浏览器最基本也是最核心的安全功能。web是构建在同源策略基础之上的,浏览器只是同源策略的一种实现
- 同源策略会阻止一个域的javascript和另外一个域的内容剂型交互,所谓同源,指的是两个页面具有相同的协议、主机和端口号
2.什么是跨域?
当一个请求的url的协议、域名、端口三者之间任意一个与当前url不同即为跨域
3.非同源限制
-
无法读取非同源网页的Cookie、LocalStorage、IndexedDB
-
无法接触非同源网页的dom元素
-
无法向非同源地址发送ajax请求
ajax(AsynchronousJavascript + XML)是一种技术:js调用异步组件并使用格式化的数据来更新web页面上的内容或操作过程
4. preflight request
4.1 什么时候发送预检请求
浏览器限制从浏览器发起的跨域http请求,像xmlhttprequest和fetch都遵循同源策略,限制跨域请求的方式:
- 浏览器限制发起跨域请求
- 浏览器可以正常发起,但是返回结果被浏览器拦截
浏览器一般采用第二种方式限制,也就是说请求已到达服务器,并且又可能对数据库里的数据进行了限制操作,但是返回的结果被浏览器拦截了,那么我们就获取不到结果,但是可能对数据库里的数据产生了影响
为了防止这种情况的发生,规范要求,对这种可能对服务器数据产生副作用的http请求方法,浏览器必须先使用OPTION方法发起一个预检请求,从而获知服务器是否允许该跨域请求:如果允许,就发送带数据的真实请求;如果不允许,则阻止发送带数据的真实请求
4.2 option 请求触发条件
-
使用以下http方法:
PUT/DELETE/CONNECT/OPTIONS/TRACE/PATCH
-
人为设置了以下集合之外的首部字段
Accept/Accept-Language/Content-Language/Content-Type/DPR/Downlink/Save-Data/Viewport-Width/Width
-
Content-Type的值不属于下列之一
application/x-www-form-urlencoded, multipart/form-data, text/plain
5.解决方案
5.1 后段解决方案
app.use(async (ctx, next) => {
ctx.set("Access-Control-Allow-Origin", ctx.headers.origin);
ctx.set("Access-Control-Allow-Credentials", true);
ctx.set("Access-Control-Request-Method", "PUT,POST,GET,DELETE,OPTIONS");
ctx.set(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept, cc"
);
if (ctx.method === "OPTIONS") {
ctx.status = 204;
return;
}
await next();
});
5.2 Node正向代理
- 利用服务请求不会跨域的特性,让接口和当前站点同域
代理前:
代理后:
5.3 nginx反向代理
- 通过反向代理的方式,保证当前域名能够获取到静态资源和接口