跨域是前端在本地开发过程会经常遇到的问题,有的时候大部分是让后端童鞋帮忙处理下就好了。哈哈 但是作者有自己的态度,基本都是自己解决这个问题,俗话说自己动手 丰衣足食呀。废话就不多说了,让我们来先了解跨域是如何产生的。
1.什么是跨域?
跨域:指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制。
例如:a页面想获取b页面资源,如果a、b页面的协议、域名、端口、子域名不同,所进行的访问行动都是跨域的,而浏览器为了安全问题一般都限制了跨域访问,也就是不允许跨域请求资源。注意:跨域限制访问,其实是浏览器的限制。
同源策略:是指协议,域名,端口都要相同,其中有一个不同都会产生跨域;
跨域示例:后端开发的童鞋已经将接口部署到测试环境,前端还在本地进行接口调试阶段,此时就会出现跨域
2.如何解决跨域
1.跨文档通信 API:window.postMessage() 调用postMessage方法实现父窗口 A.com 向子窗口 B.com 发消息(子窗口同样可以通过该方法发送消息给父窗口。主要解决以下几种场景
- 页面和其打开的新窗口的数据传递
- 多窗口之间消息传递
- 页面与嵌套的iframe消息传递
- 上面三个场景的跨域数据传递
// 父窗口打开一个子窗口
var openWindow = window.open('http://A.com', 'hello');
// 父窗口向子窗口发消息(第一个参数代表发送的内容,第二个参数代表接收消息窗口的url)
openWindow.postMessage('how are you', 'http://B.com');
复制代码
2.JSONP
JSONP 是服务器与客户端跨源通信的常用方法。最大特点就是简单适用,兼容性好(兼容低版本IE),缺点是只支持get请求,不支持post请求。
核心思想:网页通过添加一个
- JQ的方式
$.ajax({
url: 'http://A.com/login',
type: 'get',
data: {},
xhrFields: {
withCredentials: true // 前端设置是否带cookie
},
crossDomain: true, // 会让请求头中包含跨域的额外信息,但不会含cookie
});
复制代码
- 原生js引入的方式
var xhr = new XMLHttpRequest();
// 前端设置是否带cookie
xhr.withCredentials = true;
xhr.open('post', 'http://www.A.com/login', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send('user=admin');
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
alert(xhr.responseText);
}
};
复制代码
3.Nginx(反向代理)
Nginx处理跨域的方式其实就是反向反向代理。那什么是反向代理呢?通俗一点说就是我们不能直接访问到目标服务器,这个时候我们就需要通过代理的方式实现,这种对于用户还是我们开发来说都是无感的,因为这些处理都是nginx帮我们处理好了。配置代码如下
listen 8081;
server_name localhost 127.0.0.1; //当前服务的域名
#location ~ ^/(yunpos|agent)/ { //添加访问目录为/apis的代理配置
#proxy_pass https://manage-api.yingqianpos.com; #线上后台api
#proxy_pass https://yunpos-manageapi.cs.kemai.com.cn; #测试后台api
#}
复制代码
4.Node服务端代理
1.koa-server-http-proxy是koa2的中间件
const Koa = require('koa')
const app = new Koa()
const proxy = require('koa-server-http-proxy')
app.use(async (ctx, next)=> {
ctx.set('Access-Control-Allow-Origin', '*');
ctx.set('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild');
ctx.set('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS');
if (ctx.method == 'OPTIONS') {
ctx.body = 200;
} else {
await next();
}
});
app.use(proxy('/yunpos', {
target: 'https://manage-gray.yingqianpos.com',
pathRewrite: { '^/yunpos': '' },
changeOrigin: true
}))
app.listen(8081)
复制代码
2.# http-proxy-middleware是node.js提供的代理方式
const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
const app = express();
app.use('/yunpos',
createProxyMiddleware({
target: 'https://manage-gray.yingqianpos.com',
changeOrigin: true,
pathRewrite: {
'^/yunpos': '', // rewrite path
},
}));
app.listen(8081)
复制代码
虽然现在vue、react的框架已经跨域的请求处理,这对我们前端童靴来说是个福音。但是还是存在某些传统的项目还是需要需要我们通过其他的方式实现跨域请求。node服务端代理以及nginx反向代理目前是我用的最多。大家肯定有更好的方式,希望可以分享给俺呀。老规矩 看过的同学麻烦动动小手点赞呀