跨域问题以及跨域问题解决(回答开发中怎么处理跨域的问题)

跨域

问题说明:当下最流行的就是前后端分离开发,前端项目和后端接口并不在同一个域名下,那么必然会出现跨域问题,这种跨域问题是出现在开发的过程中的,而部署上线出现的跨域问题是生产环境中的,与前端开发无关系,由运维人员负责,可以使用Nginx反向代理,在此不做介绍。
关于开发环境中的跨域问题的几种解决方式如下:

  • jsonp(原理是动态添加一个script标签,src属性没有跨域限制,存在安全隐患,只支持get请求)
  • vue-cli代理(webpack反向代理配置devserver配置代理地址)
  • cors(后端小伙伴做跨域资源共享配置,前端设置允许携带cookie值
    axios.defaults.withCredentials=true)

为什么会有跨域的错误

你项目中请求的接口地址与你本地的服务器不同源。

  • 协议,域名,端口 有一个不相同(不同源)

就会出现跨域请求,如果此时你的后端接口是允许跨域的,则浏览器也不会报错,所以需要解决跨域错误的情况要满足如下三个条件:

  • 你的浏览器不给力(同源策略)。

    可以安装这个chrome插件,来绕过浏览器的限制。
    在这里插入图片描述

  • 你的请求真是跨域了。
    在这里插入图片描述

  • 后端请求不允许跨域请求。

所以,出现跨域的请求,如果后端接口服务器已经处理了,则可以正常访问;而如果后端没有处理,则会报错,此时,就需要我们前端来介入了。
在这里插入图片描述
在这里插入图片描述

vue项目中跨域如何解决

先验知识:

​ 如果是两台服务器之间相互请求接口,则不会出现跨域请求错误(跨域请求错误是浏览器报的)

思路:

​ 通过本地服务器来代理请求

在这里插入图片描述

准备工作

安装axios,express这两个包。

# 用来发ajax请求
npm i axios 
# 用来快速创建接口服务器,模拟后端
npm i express -D

准备服务器

在src/server下创建文件express_server.js内容如下:

const express = require('express')
const url = require('url')
const app = express()
function fullUrl (req) {
  console.dir(req.headers.host)
  return url.format({
    protocol: req.protocol,
    host: req.get('host'),
    pathname: req.originalUrl
  })
}
app.use((req, res, next) => {
  // console.dir(req)
  console.log(Date.now(), fullUrl(req))
  // 打开下面四句代码用来处理跨域请求,如果开启,则不会出现跨域错误
  // res.header('Access-Control-Allow-Origin', '*')
  // res.header('Access-Control-Allow-Headers', 'Content-Type')
  // res.header('Access-Control-Allow-Methods', '*')
  // res.header('Content-Type', 'application/json;charset=utf-8')
  next()
})
app.get('/api/v1_0/user', (req, res) => {
  res.json({
    a: 1, b: 2
  })
})
app.get('/api/v1_0/channels', (req, res) => {
  res.json({
    a: 11, b: 2
  })
})

app.listen('5000', () => {
  console.log(5000)
})

启动服务器

node express_server.js

测试

http://localhost:5000/api/v1_0/user

准备客户端

对axios进行二次封装

在src/util/request.js

import axios from 'axios'
const instance1 = axios.create({
  // baseURL: 'http://ttapi.research.itcast.cn'
  baseURL: 'http://localhost:5000'
  // baseURL: '/api'
})

const instance2 = axios.create({
  baseURL: 'http://www.com2.com'
})

export { instance1, instance2 }
export default instance1

在login.vue中发起请求

import ajax from '@/utils/request.js'
async login () {
      
      await ajax({
        methods: 'get',
        url: '/api/v1_0/channels'
        // url: 'api/user'
      })
}

观察结果

跨域错误
在这里插入图片描述

解决跨域

后端支持跨域

把express写的接口服务器中的跨域处理打开:

app.use((req, res, next) => {
  // console.dir(req)
  console.log(Date.now(), fullUrl(req))
  // 打开下面四句代码用来处理跨域请求,如果开启,则不会出现跨域错误
   res.header('Access-Control-Allow-Origin', '*')
   res.header('Access-Control-Allow-Headers', 'Content-Type')
   res.header('Access-Control-Allow-Methods', '*')
   res.header('Content-Type', 'application/json;charset=utf-8')
  next()
})

重启服务器,再发请求。

vue配置 vue-cli代理服务

通过在vue.config.js中补充devServer项的配置。

具体步骤:

  • 更改request.js中的baseUrl的设置

    去掉baseUrl即可。此时,没有配置基地址,它会自动补全http://localhost:8080
    在这里插入图片描述

  • 补充vueconfig.js中的配置

vue.config.js

module.exports = {
  publicPath: './'
  devServer: {
  // 代理把/api的请求转到target里面
     proxy: {
       '/api': {
         target: 'http://localhost:5000',
  //       // changeOrigin: false, // 请求头是 本地服务器 localhost:8080
         changeOrigin: true, // 请求头是 target
         pathRewrite: {
  //         // '^/api': '/api/haha'
  //         // 把路径中的/api改成/api/haha
  //         // 示例:http://localhost:8080/api/v1_0/user ----> http://localhost:5000/api/haha/v1_0/user

            '^/api': '' // 路径重写
           // 把路径中的/api改成空格,相当于去掉/api
           // 示例:http://localhost:8080/api/v1_0/user ----> http://localhost:5000/v1_0/user

  //         '^/api': '/api11'
  //         // 把路径中的/api 改成/api11
  //         // 示例:http://localhost:8080/api/v1_0/user ----> http://localhost:5000/api11/v1_0/user
         }

  //     }
  //   }
  // }
}

注意:

  • 修改了配置文件要重启服务
  • 时时观察后端服务器的输出效果

小结

跨域不是vue的问题;

原因:

  • 浏览器的同源策略
  • 后端接口没有对请求进行跨域处理

在vue在开发阶段,它会起一个服务器,(localhost:8080) ,我们可以通过vue.config.js中设置代理,通过服务器来去向接口发请求。

如果打包上线(dist目录),则devServer.proxy就无法用了。


版权声明:本文为weixin_43909743原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。