什么是跨域
首先需要了解到浏览器的同源策略,同源策略是最核心也是最基本的安全功能,缺少同源策略浏览器的正常功能可能会受到影响。同源策略会阻止一个域的javascript脚本和另外一个域的能容进行交互。同源(即指在同一个域)就是两个页面具有相同的协议(protocol)、主机(host)和端口号(port)。
当一个请求url的协议、域名、端口三个之间任意一个与当前页面url不同即为跨域。
Vue中用Axios解决跨域问题
配置代理可解决使用Axios不能直接进行跨域的问题。
原理:客户端请求服务端的数据存在跨域问题,而服务器和服务器之间可以相互请求数据,没有跨域的概念(前提是服务器没有设置禁止跨域的权限问题),也就是说,可以配置一个代理的服务器请求另一个服务器中的数据,然后把请求出来的数据返回到代理服务器中,代理服务器再返回数据给我们的客户端,如此即可实现跨域访问数据。
步骤一:配置baseURL,(即下面代码段中的 axios.defaults.baseURL = '/api/',作用是我们每次发送的请求都会带一个/api/的前缀。)
在main.js中,配置数据所在服务器的前缀(即固定部分),代码如下:
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import './plugins/element.js'
import axios from 'axios'
// 配置请求的根路径
axios.defaults.baseURL = '/api/'
// 挂载到原型对象之前 先设置拦截器 通过axios请求拦截器添加token,保证拥有获取数据的权限
//axios.interceptors.request.use(config => {
//在 request 拦截器中, 展示进度条 NProgress.start()
//NProgress.start()
// 为请求头对象添加Token验证的Authorization字段
//config.headers.Authorization = window.sessionStorage.getItem('token')
// 最后都必须 return config
//return config
//})
// 在 response 拦截器中, 隐藏进度条 NProgress.done()
//axios.interceptors.response.use(config => {
//NProgress.done()
//return config
//})
// 原型上挂载axios, 所有组件都可以通过this.$http来请求
Vue.prototype.$http = axios
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
步骤二:配置代理,(配置在vue.config.js文件中的proxyTable字段中)
devServer: {
proxy: {
'/api/': {
target:'http://127.0.0.1:8888/api/private/v1/', // 你请求的第三方接口
changeOrigin:true, /* 在本地会创建一个虚拟服务端,然后发送请求的数据,
并同时接收请求的数据,这样服务端和服务端进行数据的交互就不会有跨域问题 */
pathRewrite:{ // 路径重写,
/* 替换target中的请求地址,也就是说以后你在请求
http://127.0.0.1:8888/api/private/v1/这个地址的时候直接写成/api/即可。 */
'^/api/': ''
}
}
},
}
步骤三:具体使用axios的地方,修改为去掉上面设置的前缀之后的url即可
// 获取权限列表
async getRightsList(){
// 请求‘http://127.0.0.1:8888/api/private/v1/right/list’这个接口
const {data:res} = await this.$http.get('rights/list')
console.log(this.$http.get('rights/lisqt'))
if(res.meta.status !== 200){
return this.$message.error('获取权限列表失败!')
}
this.rightsList = res.data
console.log(this.rightsList)
}
}
最后附上一个详细的vue.config.js的配置
module.exports = { // 项目部署的基础路径 // 我们默认你的应用将会部署在域名的根部,比如 https://www.xxx.com/ // 如果你的应用时部署在一个子路径下,那么你需要在这里指定子路径。 // 比如,如果你的应用部署在https://www.xxx.com/public/ // 那么将这个值改为 `/public/` // 部署生产环境和开发环境下的URL:可对当前环境进行区分,baseUrl 从 Vue CLI 3.3 起已弃用,要使用publicPath /* baseUrl: process.env.NODE_ENV === 'production' ? './' : '/' */ publicPath: process.env.NODE_ENV === 'production' ? '/public/' : './', /* 输出文件目录:在npm run build时,生成文件的目录名称 */ outputDir: 'dist', /* 放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录 */ assetsDir: "assets", /* 是否在构建生产包时生成 sourceMap 文件,false将提高构建速度 */ productionSourceMap: false, /* 默认情况下,生成的静态资源在它们的文件名中包含了 hash 以便更好的控制缓存,你可以通过将这个选项设为 false 来关闭文件名哈希。(false的时候就是让原来的文件名不改变) */ filenameHashing: false, /* 代码保存时进行eslint检测 */ lintOnSave: true, /* webpack-dev-server 相关配置 */ devServer: { /* 自动打开浏览器 */ open: true, /* 设置为0.0.0.0则所有的地址均能访问 */ host: '0.0.0.0', port: 8066, https: false, hotOnly: false, /* 使用代理 */ proxy: { // string | Object '/api': { /* 目标代理服务器地址 */ target: 'http://xxx/', /* 允许跨域 */ changeOrigin: true, pathRewrite: { '^/api': '' //规定请求地址以什么作为开头 } }, }, }, }