Vue+nginx 实现跨域访问
1、跨域和同源策略
什么是同源策略?
同源策略是指浏览器处于安全考虑的情况下,只允许本域下的借口进行交互。不同源的客户端在没有授权的情况下是不允许获取对方资源的。
本域指的是什么?
同协议:例如相同的http或https
同域名:例如https://baidu.com/aaa 和 https://baidu.com/bbb
同端口:例如8080端口
一个示例:
跨域解决方案:
JSONP
CORS
nginx反向代理
降域
postMessage
JSONP:最早的解决方案,利用script标签可以跨域的原理实现,只支持get请求
CORS:同源策略
优势:
在服务端进行控制是否允许跨域,可自定义规则
支持各种请求方式
缺点:
会产生额外的请求
阮一峰对CORS的解析:http://www.ruanyifeng.com/blog/2016/04/cors.html
nginx反向代理
思路是:利用nginx反向代理把跨域为不跨域,支持各种请求方式
缺点:需要在nginx进行额外配置,语义不清晰
降域和postMessage:
https://www.jianshu.com/p/7666e1ffb8c6
当没api接口遇到跨域问题时,会报XMLHttpRequest跨域提示:
当使用CORS策略,解决跨域问题时,我的做法是在服务端设置允许访问的接口地址:
app.use(async (ctx, next) => { //添加允许请求头 // ctx.append('Access-Control-Allow-Origin', '*') // ctx.append('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild') // ctx.append('Access-Control-Allow-Methods', 'PUT,POST,GET,DELETE,OPTIONS,PATCH') // //ctx.append('Content-Type', 'application/json;charset=utf-8') // console.log(`Process ${ctx.request.method} ${ctx.request.url}...`); // logger.info(`Process ${ctx.request.method} ${ctx.request.url}...`) //http 预请求处理(post/put/delete 请求在正式请求之前会先发送一个OPTIONS的预请求,只需要把这个OPTIONS的预请求正常返回,后续的请求就会正常执行) if (ctx.request.method === 'OPTIONS') { ctx.body = "OK" } else { //继续执行api请求 await next(); } });
因为项目中使用的是vue+node.js实现,而vue自身可以设置proxy实现跨域,所以最终采用vue proxy+nginx反向代理,实现跨域
2、Vue 设置代理实现本地跨域
当前项目使用vue-cli3.0版本构建
首先在根目录下创建vue.config.js文件,这个配置文件会在运行项目的时候自动加载
module.exports = { runtimeCompiler: true, publicPath: '/', // 设置打包文件相对路径 devServer: { open: process.platform === 'darwin', host: '127.0.0.1', port: 3000, // open: true, //配置自动启动浏览器 proxy: { '/api': { // target: process.env.VUE_APP_BASE_URL, //对应自己的接口 target: 'http://www.xxx.com', //对应自己的接口 changeOrigin: true, ws: true, pathRewrite: { '^/api': '' } } } }, }
解释:
proxy对象标识,对/api 开头的接口实现代理
target:’’,代理的接口地址,
changeOrigin:true,是否跨域
secure:false, 如果是https接口,需要配置这个参数
pathRewrite:{},//重写api路径,因为原来接口中不存在’/api’,我们人为加上去就是为了标识哪些接口需要实现代理,但是真正访问接口的时候还是要把接口uri中的‘/api’替换为‘’
我们不仅可以为’/api’实现代理,也可以为其他具有同类功能的接口实现代理,比如我们的接口是发布在多个微服务中的,就需要我们设置多个代理地址,
这时,就不能对axios设置统一的baseURL
//axios.defaults.baseURL = ‘’
在使用axios请求接口的时候,如果需要跨域,则在请求接口前加载‘/api’,例如:
const server=’/api’
const uri=server+’/ patient_survey/findByPage’
axios.post(uri).then(res=>{})
配置完成之后本地就可以跨域访问了,
通过浏览器F12查看请求地址为:
但是实际的接口请求地址为:devServer.proxy.target中的地址
所以实际请求的uri为:http:www.xxx.com/patient_survey/findByPage
3、vue+nginx实现服务端跨域
但是把vue项目打包发布之后,调用接口会提示404错误,这时还需要在nginx中做一下反向代理
在服务器中找到nginx的配置文件nginx.config
在需要添加反向代理的配置项中添加如下:
location /api {
rewrite ^.+api/?(.*)$ /$1 break; //可选参数,正则验证地址
include uwsgi_params; //可选参数,uwsgi是服务器和服务端应用程序的通信协议,规定了怎么把请求转发给应用程序和返回
proxy_pass http://www.xxx.com;// 此处修改为自己的请求地址,必填
}
server { listen 80; server_name xxx.com; charset utf8; location / { root /data/release/xxx; index index.html; proxy_pass http://127.0.0.1:8003; } location /api { rewrite ^.+api/?(.*)$ /$1 break; include uwsgi_params; proxy_pass http://www.xxx.com; } error_page 404 /404.html; location = /40x.html { } error_page 500 502 503 504 /50x.html; location = /50x.html { } }
设置完成后 重启nginx
- nginx –s reload
完成后服务器应该也能实现跨域
参考:
https://www.cnblogs.com/zhaohongcheng/p/11250161.html
4、vue配置环境变量
在实现vue的跨域访问之后,为了方便本机调试和发布,可以在vue中设置不同的环境变量,使项目在不同的环境中自动调用不同的接口地址
需要文件:
在vue项目根目录下创建三个文件
.env 无论开发环境还是生成环境都会加载
.env.development 开发环境加载这个文件
.env.production 生成环境加载这个文件
如果需要其他环境,可以继续添加其他环境的配置文件
.env 文件内容:
NODE_ENV = production
.env.development 文件内容:
NODE_ENV = development
VUE_APP_BASE_URL = http://localhost:3000/
.env.production 文件内容:
NODE_ENV = production
VUE_APP_BASE_URL = http://www.xxx.com/
(其中’VUE_APP_’是固定前缀,不可以更改)
文件加载顺序:
首先加载.env文件,判断当前的项目环境,
如果是开始环境,则继续加载.env.development的内容,
如果是生产环境,则加载.env.production的内容,
ps:测试发现,当前的系统环境并不是.env文件中的NODE_ENV =xxx 确定的,而是根据实际情况决定,
如在ide中使用npm run serve调试,则加载的是.env.development文件
如果执行npm run build 之后发布到服务器,则加载的是.env.production文件
pageage.json的scripts部分如下
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
在项目main.js文件可以打开查看当前的系统变量:
console.log('process.env',process.env)
设置完之后,在开始的vue.config.js代理文件中,将target指向改为: process.env.VUE_APP_BASE_URL
之后,vue会根据执行环境的不同自动加载相应的接口地址