前后端分离项目主流的跨域解决方案

三种主流的跨域解决方案(vue-cli3 package.json中配置跨域)
最近学习nodejs的express框架,对CORS(跨域资源共享Cross-origin resource sharing)比较感兴趣,看过上面的文章后在本地测试发现很多容易忽略的问题导致无法实现跨域,现将解决方案记录如下:

跨域的解决方案:

1.CORS跨域资源共享(后端设置)

弊端:
如果Access-Control-Allow-Origin 设置单一源不能同时设置多个
如果 Access-Control-Allow-Origin 设置为 * 不允许携带 cookie

1.1 使用cors插件处理
1.2 使用自定义中间件设置响应头处理
1.3 使用app.use('*',callback)全局拦截处理响应头

具体实现如下(三个方法选择其一即可):

后端代码实现
服务端node.jssrc/app.js启动文件配置如下:

const express = require('express')
const bodyParser = require('body-parser')//用于解析请求体的中间件,否则无法获取req.body
const app = express()
const models = require('./db/models/index.js')
const baseUrl = '/todo_api'
const cors = require('cors')

//1.cors插件处理跨域
app.use(cors())

//2.自定义中间件处理跨域
/* let allowCrossDomain = function(req, res, next) {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
    res.header('Access-Control-Allow-Headers', 'Content-Type, token');
    res.header('Access-Control-Allow-Credentials','true');
    console.log('zqf123')
    next();
};
app.use(allowCrossDomain); */

//3.app.all('*')全局拦截处理跨域
/* app.all('*', (req, res, next)=>{
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
    res.header('Access-Control-Allow-Headers', 'Content-Type, token');
    res.header('Access-Control-Allow-Credentials',true);
    console.log('res', res)
    next();
}) */

前端代码实现:
在封装的全局拦截请求http.js里设置绝对路径的的baseURL前缀地址,一般为server地址,同时可以根据需要设置header的值。

import axios from 'axios'
// 全局请求头设置
axios.defaults.headers = {
    'Content-Type': 'application/json',
    'token': 'zqf666',
}
//统一设置请求前缀
axios.defaults.baseURL = "http://127.0.0.1:3030/todo_api"

最后将http.js引入到前端项目的入口文件里

//react项目的src/index.js文件
import './http/http.js'

//vue项目的src/main.js文件
import './http/http.js'

容易出现的问题:
由于全局设置了请求头Content-Typetoken,而在node.js里最开始处理CORS时设置为res.header('Access-Control-Allow-Headers', 'Content-Type');导致浏览器控制台报错无法跨域,在postman工具上测试又可以拿到返回的数据,最后用firefox浏览器打开测试了一下虽然还是跨域但是浏览器给出了具体的原因,终于解决。

image.png

2.Http Proxy 代理

弊端:
只能在本地开发使用,线上部署需要搭配Nginx等代理服务器

2.1 在vue项目中使用代理
2.1.1根目录下创建配置文件vue.config.js

module.exports = {
  "lintOnSave": false,//忽略eslint代码检查
    "devServer": {
      "proxy": {
        "/api": {
          "target": "http://127.0.0.1:3030/",//代理的地址
          "changeOrigin": true,
          "ws": true,
          "pathRewrite": {
            "^/api": ""
          }
        }
      }
    }
}

2.1.2不使用vue.config.js配置文件
vue-cli3 中取消了配置文件 vue.config.js,网上的跨域处理多为新建配置文件 vue.config.js,如果不想增加配置文件,则可以在package.json增加配置:

  • package.json 中加入 vue 字段(下面的代码段)
  • 如果请求的地址不是 /api,借助 pathRewrite/api 替换
  • axios 进行网络请求,在封装 axios 时设置 baseURL: '/api'而非绝对路径
"eslintConfig": {
//eslint代码检查规则,代替.eslintrc.js配置文件
},
"vue": {
//代替vue.config.js配置文件
    "lintOnSave": false,//忽略eslint代码检查
    "devServer": {
      "proxy": {
        "/api": {
          "target": "http://127.0.0.1:3030/",//代理的地址
          "changeOrigin": true,
          "ws": true,
          "pathRewrite": {
            "^/api": ""
          }
        }
      }
    }
  }

容易出现的问题:
1.该方法必须在vue-cli3脚手架生成的项目(目录下没有vue.config.js文件)里使用;

  1. package.json的vue字段里设置代理,则vue.config.js文件不能存在,否则package.json的配置会被忽略,如下图:
    image.png

vue-cli3官方文档说明

image.png

2.2 在react项目中使用代理
2.2.1在 package.json 中加入 proxy字段并设置相关代理
image.png

react官方文档说明

官方文档说明

2.2.2在 在config配置文件里设置相关代理
通过create-react-app脚手架安装的react项目只有node_modulespublicsrc文件夹,很多配置文件都没有了,那是因为webpack,babel等都是被creat-react-app封装到了react-scripts这个项目当中,包括基本启动命令都是通过调用react-scripts这个依赖下面的命令进行启动。通过npm run eject将原本creat react appwebpack,babel等相关配置的封装弹射出来,然后就可以在项目的目录下config配置文件,修改代理即可。
image.png

3.使用插件代理

后端实现:
1.安装中间件http-proxy-middleware:
npm i http-proxy-middleware -d
2.在src/app.js中引入中间件并添加配置

// 引用依赖
var express = require('express');
var createProxyMiddleware = require('http-proxy-middleware');
var app = express();
// 创建代理设置中间件选项
var exampleProxy = createProxyMiddleware ( {
        target: 'http://127.0.0.1:3030', // 目标服务器 host
        changeOrigin: true,               // 默认false,是否需要改变原始主机头为目标URL
        ws: true,                         // 是否代理websockets
        pathRewrite: {
            '^/api' : '',     // 重写请求
        },
    };);

// 使用代理
    app.use('/api', exampleProxy);
    app.listen(3000);

请求地址示例:
axios.get(/api/xxx)
前端实现:
axios前缀设置
axios.header.baseURL='/api'

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,784评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,745评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,702评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,229评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,245评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,376评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,798评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,471评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,655评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,485评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,535评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,235评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,793评论 3 304
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,863评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,096评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,654评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,233评论 2 341