跨域定义:
跨域的解释:当前所在页面的url去请求后台提供的url的时候,这两个url的相比较之下,如果协议类型、域名、端口号
其中任何一个不一致就会发生跨域问题
序号 | 当前所在页面的url | 后台提供的url | 跨域情况 | 原因 |
---|---|---|---|---|
1 | http://localhost:8080 |
http://localhost:8080/zbApi/user/auto_login |
不跨域 | 协议类型、域名、端口号都一致 |
2 | http://localhost:8080 |
https://localhost:8080 |
跨域 | 协议类型不相同 http| https |
3 | http://localhost:8080 |
http://ymzp.0633hr.com/api/app/user/auto_login |
跨域 | 域名不同 |
4 | http://localhost:8080 |
http://localhost:8081 |
跨域 | 端口号不相同 8080 | 8081 |
项目简介:我是使用脚手架创建的vue项目,且是前后端分离的项目。
前端用的vue.js框架,后端用的是thinkcmf或者node.js框架。
既然是前后端分离的项目,前端爱用什么框架就用什么框架,后端爱用什么框架就用什么框架,前后端并不干预,就看公司的要求了,都是可以随意搭配的
。
就像我们公司,1个项目前端用vue.js,后端用的是node.js。另一个项目前端用vue.js,后端用的是thinkcmf
问题分析:
开发阶段项目在本地,因此属于开发模式。
默认情况下,暴露在浏览器中的请求如果为localhost的话(http://localhost:8080/zbApi/user/auto_login
),那么是不会跨域的,因为你是在本地去请求本地的数据,实际上是序号1
的情况。
但如果你暴露在浏览器中的请求的url如果为远程服务器的地址(http://ymzp.0633hr.com/api/app/user/auto_login
)的话,那么肯定是跨域的,因为你是在本地去请求远程服务器上的数据,实际上是序号3
的情况。
结论:
我这种情况属于后者,所以报了如下的错误。
Access to XMLHttpRequest at 'http://ymzp.0633hr.com/api/app/user/auto_login' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
解决办法
既要最终实现请求的地址变为
http://ymzp.0633hr.com/api/app/user/auto_login
,也要实现暴露在浏览器中的请求地址为http://localhost:8080/zbApi/user/auto_login
,其中的一种做法就是:拦截请求的url中的指定内容,并做拦截后的处理操作
。下面就演示这种做法。
拿公司的http://ymzp.0633hr.com/api/app/user/auto_login
和http://ymzp.0633hr.com/api/app/order/get_circle_nearby
接口为例。
步骤一:首先操作的是config文件夹下的index.js文件
。可以看到proxyTable
里面没有配置任何信息,接下来主要是配置proxyTable
'use strict'
const path = require('path')
module.exports = {
dev: {
// Paths
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {
}
},
host: 'localhost', // can be overwritten by process.env.HOST
port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
autoOpenBrowser: false,
errorOverlay: true,
notifyOnErrors: true,
poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
devtool: 'cheap-module-eval-source-map',
cacheBusting: true,
cssSourceMap: true
},
build: {
index: path.resolve(__dirname, '../dist/index.html'),
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
assetsPublicPath: '/',
productionSourceMap: true,
devtool: '#source-map',
productionGzip: false,
productionGzipExtensions: ['js', 'css'],
bundleAnalyzerReport: process.env.npm_config_report
}
}
步骤二:拦截请求中的url指定内容,拦截到了,就可以对跨域问题尽情蹂躏了
proxyTable: {
'/zbApi': { // 拦截请求url中的/zbApi
}
},
步骤三:将项目中所有接口的公共的部分抽取出来,作为config文件夹下的index.js文件
中的target的值。即:公共部分为 http://ymzp.0633hr.com/api/app
proxyTable: {
'/zbApi': { // 拦截请求url中的/zbApi
target: 'http://ymzp.0633hr.com/api/app', // 真实的请求地址
}
},
步骤四:补全如下信息
proxyTable: {
'/zbApi': { // 拦截请求url中的/zbApi
target: 'http://ymzp.0633hr.com/api/app', // 真实的请求地址
// secure: true, // true:使接口 允许前缀为https
changeOrigin: true, // true:开启代理,使接口 允许跨域
pathRewrite: {
'^/zbApi': ' '
}
}
},
步骤五.在main.js
文件中,将/zbApi
作为axios的基类url 。 直接将/zbApi
赋值给axios的baseURL属性即可。
后续使用axios请求任何接口,都会在url前面接/zbApi
进行请求数据。
import axios from 'axios'
axios.defaults.baseURL = '/zbApi'
步骤五:接口演示。
虽然参数url
中只写了/user/auto_login
,但由于步骤五设置了基类url,所以就成了zbApi/user/auto_login
。
再加上参数url
设置成了相对路径,因此会前拼开发模式下的浏览器地址.
最终请求的url变成了http://localhost:8080/zbApi/user/auto_login
this.$zbhttp({
method: "post",
// 虽然只写了/user/auto_login,由于步骤五,所以实际上url是http://localhost:8080/zbApi/user/auto_login
url: "/user/auto_login",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"Api-Version": "v319",
Token:
"4c5d143a69d88913944cc02886a80096e9020f59f6601056855b2a6a2298b2ef",
"Device-Type": "ios"
}
}).then(res => {
console.log(res);
});
-
步骤六:成功拿取数据
- 步骤七:最终
config文件夹下的index.js文件
配置信息如下
'use strict'
const path = require('path')
module.exports = {
dev: {
// Paths
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {
'/zbApi': { // 拦截请求url中的/zbApi
target: 'http://ymzp.0633hr.com/api/app', // 真实的请求地址
// secure: true, // true:使接口 允许前缀为https
changeOrigin: true, // true:开启代理,使接口 允许跨域
pathRewrite: {
'^/zbApi': ' '
}
}
},
host: 'localhost', // can be overwritten by process.env.HOST
port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
autoOpenBrowser: false,
errorOverlay: true,
notifyOnErrors: true,
poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
devtool: 'cheap-module-eval-source-map',
cacheBusting: true,
cssSourceMap: true
},
build: {
index: path.resolve(__dirname, '../dist/index.html'),
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
assetsPublicPath: '/',
productionSourceMap: true,
devtool: '#source-map',
productionGzip: false,
productionGzipExtensions: ['js', 'css'],
bundleAnalyzerReport: process.env.npm_config_report
}
}