//服务器端口号
PORT:3001,
//CORS跨域相关信息
CORS:{
//允许那个源跨域
ALLOW_ORIGIN:“http://127.0.0.1”,
//设置允许跨域的请求方法
ALLOW_METHODS:‘PUT,POST,GET,DELETE,OPTIONS,HEAD’,
//允许的请求头有哪些
HEADERS:‘Content-Type,Content-Length,Authorization,Accept,X-Requested-With’,
//是不是在跨域请求中可以携带资源凭证,是否允许携带cookie等等
CREDENTIALS:true
}
//SEESSION存储相关信息
SESSION:{
secret:‘zfpx’,
saveUninitialized:false,
resave:false,
//cookie
cookie:{
maxage:1000
}
}
}
axios代码
//默认请求的时候添加请求前缀
axios.defaults.baseURL=‘http://127.0.0.1:6000’;
//如果前端配置了这个withCredentials=true,后段设置Access-Control-Allow-Origin不能为 " * ",必须是你的源地址
//在跨域请求时,会携带用户凭证
axios.defaults.withCredentials=true;
//
axios.defaults.headers[‘Content-Type’]=‘application/x-www-form-urlencoded’;
//
axios.defaults.transformRequest=function(data){
if(!data) return data;
let result =``;
for(let attr in data){
if(!data.hasOwnProperty(attr)) bareak;
result+=&${attr}=${data[attr]}
;
}
return result.substring(1);
};
axios.interceptors.response.use(function onFulfilled(response){
return response.data;
},function onRejected(reason){
return Promise.reject(reason);
});
axios.defaults.validateStatus=function(status){
return /^(2|3)\d{2}$/.test(status);
}
cors的分工
前端:正常发送请求即可
后端:设置响应头,允许那些方式等等(需要处理一下options试探性请求)
CORS的安全问题
Origin字段有俩种设置方案,一种是一种是具体地址,设置成号之后,就不可携带跨域资源凭证了(因为设置为所有源请求之后
浏览器为了保证客户端数据安全)
第三种:proxy代理(常用)
需要基于webpack 和webpack-dev-server实现
webpack4.0版本要求必须安装webpack-cli
webpack默认打包src文件夹下的东西
webpack的配置代码都是在webpack.config.js里面配置的
npx webpack-dev-server启动服务(在npm5.2版本以上在本地安装的模块可以采用npx执行)
基于react和vue工程化开发都采用这种方式
部署上线之后会拿node写一个中间层
//webpack的配置代码
//引入路径模块
let path = require(‘path’);
//打包html
let HtmlWebpackPlugin=require(‘html-webpack-plugin’);
module.exports={
//指定模式 生产模式
mode:‘production’,
//打包入口
entry:‘./src/index.js’,
//打包出口
output:{
//打包出口文件名
filename:‘bundle.min.js’,
//出口文件访问路径
path:path.resolve(__dirname,‘build’)
},
//安装webpack-dev-server后可以用webpack-dev-server启动一个服务
devServer:{
//端口号
port:3000,
//显示打包进度
porgress:true,
//指定访问静态资源目录
contentBase:‘./build’,
//proxy代理
proxy:{
//拦截所有以/发生的请求
‘/’:{
// 请求地址,拦截所有以/发送的请求添加上这个地址并请求
target:‘http://127.0.0.1:3211’,
//改变源地址,开启这个之后dev-server会帮我们启一个服务做一个中层的代理,因为服务器跟服务器之间不存在跨域,
//请求到数据之后再返回给客户端,相当于拿node写了一个中间件(类似于node中间件代理的这种方式)
cahngeOrigin:true
}
}
},
//插件
plugins:[
//打包html
new HtmlWebpackPlugin({
//打包地址
template:‘./src/index.html’,
//打包文件名
filename:‘index.html’
})
]
}
//真正的webpack配置文件需要配置css,js,eslint的处理,性能优化等等
proxy的原理
是基于node中间件进行实现的,proxy相当于node给你模拟了一个nginx服务器请求,服务器请求服务器之间不存在跨域,因为跨域是浏览器对js做的安全限制,proxy请求回来的数据,在返回给客户端,解决跨域
第四种:nginx代理跨域(前端不用,都是后端干的)
先启动一个nginx服务器,nginx服务器上面安装nginx,然后在nginx上面配置一个web服务器,web服务器里面在做反向代理
// www.xxx.com转发到 www.aaa.con发送请求
#proxy服务器
server{
//端口号
listen 80;
//当前发送请求的域名
server_name www.xxx.com;
//请求http://www.xxx.com:80/api,将该请求转发到www.aaa.con,则保证请求在同一个域,解决跨域问题
//转发
location /api{
//请求的服务器
proxy_pass www.aaa.con;
//处理cookie信息进行反向代理
proxy_cookie_deom www.aaa.con www.xxx.com;
add_header Access-Control-Allow-Origin www.aaa.con;
add_header Access-Control-Allow-Credentials true;
}
}
实现原理:既然不能跨域请求,我们就通过请求到达服务前部署一个服务,将接口请求进行转发,这就是反向代理,通过一定的转发规则可以将前端的请求转发到其他服务。通过反向代理我们将前端后端项目统一通过反向代理来提供对外的服务,这样前端看上去就跟不存在跨域一样。反向代理过于繁琐,麻烦之处就在于对nginx等反向代理服务的配置,前后端分离大多数采用这种方式。
第五种:postMessage(不常用)
有俩个页面 a和b 俩个页面的数据可以通信,并可以给不同的服务器发送请求
前端代码
//a页面
//a向b拿取数据
//只是向b拿去数据并不想让他这个页面显示
//iframe引入的b页面加载完毕后在执行
iframe.οnlοad=function(){
//引入b页面里面东西,打印出来的是b页面的window
console.log(iframe.contentWindow)
//向b页面发送请求 第一个参数是发送的信息,第二个是往哪个源地址发送信息,第二个参数有俩个值第一个是具体的路径,第二个是*所有的
iframe.contentWindow.postMessage(‘哈喽’,‘127.0.0.1:2221/’)
}
//b页面发送过来信息了,接收
//监听b页面传输过来的信息
window.onmessage=function(ev){
//打印传输过来的信息
console.log(eve.data);
}
b页面
//监听a页面传输过来的信息,因为是属于127.0.0.1:2221/地址下的
window.onmessage=function(ev){
//打印传输过来的信息
console.log(eve.data);
//ev.source代表哪个源地址发送过来的信息
//给请求过来的源地址返回信息,第一个参数代表返回的数据,第二个参数代表把数据发给谁,ev.origin代表的是发送给请求源,第二个参数也可以写*
ev.source.postMessage(ev.data+‘12121’,ev.origin)
}
//发送过去之后a页面也进行接收
后台代码
server1.js
let express=require(‘express’);
app=express();
app.listen(1001,_=>{
console.log(‘ok!’)
})
app.use(express.static(‘./’));
server2.js
let express=require(‘express’);
app=express();
app.listen(2221,_=>{
console.log(‘ok!’)
})
app.use(express.static(‘./’));
访问
127.0.0.1:1001/message/a.html
127.0.0.1:2221/message/b.html
第六种:webSocket协议跨域(scoket.io方式)
用的是H5里面提供的webscoket通信协议来完成的,也可以使用这个实现实时通讯,webSocket是一个服务端跟客户端实时通讯的协议
实时聊天思路:客户端A向服务器发送请求,服务器接收到请求把信息存起来,再把信息返回给客户端B,在没有webscoket之前采用常规轮询和常规链接这种操作很麻烦性能还不好,有了scoket.io特别方便,微信就是采用scoket.io这种方式实现的实时通讯
前端代码
//websocket协议跨域代码
//引入scoket.io.js实现实时通讯
后端代码(采用node和express实现)
//首先也得安装一个socket模块,安装上去
//监听socket链接 server是node服务器创建的服务
//'connection’当我们和客户端创立连接之后会触发这个函数执行
socket.listen(server).on(‘connection’,fucntion(client){
//接收信息 client代表的是客户端 'message’监听客户端发送的信息
client.on(‘message’,fucntion(msg){
//给客户端发送返回的信息
client.send(msg+‘@@’);
});
//断开连接
client.on(‘disconnect’,fucntion(){
console.log(‘client socket has closed!’);
})
})
第七种:document.domain+iframe(基于iframe的方案,不友好)
只能实现同一个主域,不同子域之间的操作
v.xx.com和spost.xx.com这俩同在一个域下,域 xx.com
父页面A
//子页面
子页面B
document.domain+iframe注意点
必须是同一个主域下面的
限制较多
第八种:window.name+iframe(基于iframe的方案,不友好)
这种方法需要三个页面,porxy和a是同一个域 ,b是另一个域
//封装成函数
let proxy=function(url,callback){
let count=0;
let iframe=document.createElement(‘iframe’);
iframe.src=url;
iframe.οnlοad=function(){
if(count===0){
iframe.contentWindow.location=‘http://127.0.0.1:3000/proxy.html’;
count++;
return;
}
callback(iframe.contentWindow.name);
};
document.body.appendChild(iframe);
}
proxy页面
空页面
A页面
//拿到b页面里面的数据
B页面
第九种:location.hash+iframe(基于iframe的方案,不友好)
也是需要三个页面,A和C同源,A和B非同源,通过hash值实现的
A页面
//拿到b页面里面的数据
B页面
//拿到C页面里面的数据
C页面