多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
[TOC] >[success] # 解决跨域问题 在下面表格中列出了 **跨域** 的案例: | URL | 说明 | 是否允许通信 | | --- | --- | --- | | http://www.d.com/d.js <br/>http://www.d.com/w.js | 同一域名下 | 允许 | | http://www.d.com/lab/a.js <br/>http://www.d.com/src/b.js | 同一域名下不同文件夹 | 允许 | | http://www.d.com:3333/a.js <br/>http://www.d.com:4444/b.js | 同一域名不同端口 | 不允许 | | http://www.d.com/a.js <br/>http://46.33.22.44/b.js | 域名和域名对应 IP | 不允许 | | http://www.d.com/a.js <br/>http://scipt.d.com/b.js | 主域相同,子域不同 | 不允许 | | http://www.d.com/a.js <br/>http://d.com/b.js | 同一域名,不同二级域名(同上) | 不允许(cookie 这种情况下也不允许访问) | | http://www.d.com/a.js <br/>http://www.v.com/b.js | 不同域名 | 不允许 | **跨域** 是受到 **浏览器** 的 **同源策略** 的影响,在一些情况下是 **不允许通信的** 。 >[success] ## 前端解决跨域 **前端** 需要在 **vue.config.js** 文件中通过 **devServer** 中的 **proxy** 来 **配置代理** 。 **原理** :我们在 **本地开发** 的时候,通过 **vueServe** 起一个 **本地的开发服务** ,这个 **服务的地址** 一般是 **localhost** , **端口** 一般是 **8080** ,如果我们在 **本地起一个 node 服务** ,那么它的 **端口** 肯定是跟我们的 **前端服务的端口** 是不一样的,刚才在 上面表格中讲过 **同一域名不同端口** 也是 **存在跨域问题** ,是 **不在同一个域下** ,这个时候 **调用接口** 的话,受到 **同源策略** 影响,是 **无法调取成功** 的,我们可以用 **proxy** 来 **设置代理** , **它会把我们所有的接口,代理到目标URL下** ,比如接口是 **/api/getUserInfo** ,我们 **设置代理** 是 **http://localhost:4000** ,这样的话请求的接口就会被代理到 **http://localhost:4000** 下,代理后请求接口时的**URL** : **http://localhost:4000/#/api/getUserInfo** , 例子如下: **vue.config.js** ~~~ const path = require('path') // 引入nodejs的path模块 const resolve = dir => path.join(__dirname, dir) // resolve方法用来加载路径 const BASE_URL = process.env.NODE_ENV === 'production' ? '/iview-admin/' : '/' // 判断当前为开发环境还是打包环境, '/'意思是代表指定在域名的根目录下,如果要指定到iview-admin下就这样写'/iview-admin/', production为生产坏境,development为开发环境 module.exports = { lintOnSave: false, // 取消每次保存时都进行一次' ESLint '检测 publicPath: BASE_URL, // 项目的基本路径,vuecli2.0时打包经常静态文件找不到,就是需要配置这个属性为'./' chainWebpack: config => { // 配置Webpack config.resolve.alias .set('@', resolve('src')) // 引入文件时候“ @ ”符号就代表src .set('_c', resolve('src/components')) // 引入组件文件夹中的文件就可以用“ _c ”代替src/components }, productionSourceMap: false, // 打包时不生成.map文件,会减少打包体积,同时加快打包速度 devServer: { // 跨域有2种解决方案: 1. 在后端的header中配置, 2. 使用devServer来配置代理解决跨域 proxy: 'http://localhost:4000' // 这里写需要代理的URL,这里会告诉开发服务器,将任何未知请求匹配不到静态文件的请求,都代理到这个URL来满足跨域 } } ~~~ 这里的代理的 **URL地址** 以及 **端口号** 一定要与服务端 **一致** 。 >[warning] ### 注意 1. **前端配置代理** 只是在 **开发环境(develop)** 好用,便于开发,在 **生产环境(prod)** 还是 **需要由服务端解决跨域** 。 2. 这里需要注意,如果在 **前端配置代理** ,需要在 **src/config/index.js(接下来的axios封装中用到了这个文件)** 中添加一个 **逻辑判断** 如下: **src/config/index.js** ~~~ // 如果当前是生产环境用生产环境地址,如果是开发环境并且在vue.config.js中配置了代理,就用空字符串【''】,如果未配置代理就用开发环境地址 export const baseURL= process.env.NODE_ENV === 'production' ? 'http://production.com' : 'http://develop.com' // 配置了代理的情况下这样写 export const baseURL= process.env.NODE_ENV === 'production' ? 'http://production.com' : '' ~~~ >[success] ## 后端解决跨域 如果不在 **设置代理** ,可以在 **后端设置header** 来 **解决跨域问题** ,这里 **后端** 用的是 **nodejs** ,在**express(nodejs的框架)** 里使用 **app.all** 为 **所有请求** 都添加这 **3 个 header** 即可。 **app.js** ~~~ var createError = require('http-errors') var express = require('express') require('colors') var path = require('path') var cookieParser = require('cookie-parser') var logger = require('morgan') var indexRouter = require('./routes/index') var usersRouter = require('./routes/users') var app = express() // view engine setup app.set('views', path.join(__dirname, 'views')) app.set('view engine', 'jade') app.use(logger('dev')) app.use(express.json()) app.use(express.urlencoded({ extended: false })) app.use(cookieParser()) app.use(express.static(path.join(__dirname, 'public'))) app.all('*', function(req, res, next) { // 设置header res.header('Access-Control-Allow-Origin', '*') res.header('Access-Control-Allow-Headers', 'X-Requested-With,Content-Type') res.header('Access-Control-Allow-Methods','PUT,POST,GET,DELETE,OPTIONS') next() }) app.use('/', indexRouter) app.use('/users', usersRouter) // catch 404 and forward to error handler app.use(function(req, res, next) { next(createError(404)) }) // error handler app.use(function(err, req, res, next) { // set locals, only providing error in development res.locals.message = err.message res.locals.error = req.app.get('env') === 'development' ? err : {} // render the error page res.status(err.status || 500) res.render('error') }) module.exports = app ~~~