Vue解决CORS header ‘Access-Control-Allow-Origin’ missing及同源、跨域问题

通常我们在前端向后端请求数据的同时,需要做跨域申请,有时候没有做此操作,很容易出现报错,类似于Reason: CORS header ‘Access-Control-Allow-Origin’ missing此类的请求头问题,那么该如何解决,并且到底什么是跨域,请往下看。

1.什么是跨域

当一个url请求中协议、域名、端口中只要有任意一个与当前url不相同,即为跨域(可以想象当小雷在A面馆吃上一碗A套餐才算是同源,但凡不是小雷、不在A面馆、没点A套餐,只要其中一个不相同,皆不是同源)。

那么什么又是协议、域名、端口号呢?具体怎么判断,请看如下图。

本地url 请求url 跨域or同源 原因
http://www.kuayu.com http://www.kuayu.com/app.html 同源,直接访问 协议、端口、域名都相同
http://www.kuayu.com https://www.kuayu.com 跨域 http≠https,协议不通过
http://www.kuayu.com http://www.tongyuan.com 跨域 kuayu≠tongyuan,主域名不通过
http://www.kuayu.com http://qq.kuayu.com 跨域 www≠qq,子域名不通过
http://www.kuayu.com:8080 http://www.kuayu.com:8001 跨域 8080≠8001,端口号不通过

2.为什么会出现跨域

当我们了解到了什么是跨域后,就该知道为什么会出现跨域问题。

跨域的相反就是同源,同源策略是浏览器的一种自我保护机制,它是一种约定俗称的机制,在信息频繁交互的情况下,互相之间的安全隐私问题就是重中之重,所以同源就是为了保护自身安全尽量避免陌生url地址直接访问。

3.解决方案

1.JSONP

jsonp的原理就是利用<script>标签的跨域能力,也就是说<script>标签中的src属性是不受跨域影响的,就类如我们常用的<img src="图片url地址" alt="" />,就可以随时引用一些其他域名的图片供使用。

我们需要结合下述代码来实现

<script src="//i2.wp.com/www.example.com?callback=callFn">

function callFn(data){
    console.log(data)
}

优点:操作便捷,直接访问,适应性强

缺点:只支持get请求,且安全性低

2.CORS(推荐,仅需后端修改即可)

基本实现原理:CORS是一种基于HTTP头部的机制,通过在服务器端设置响应头部来允许跨域请求。浏览器会发送一个预检请求到目标服务器,目标服务器通过响应头部中的Access-Control-Allow-Origin来允许访问服务端内容。

在实际开发中,我们仅需要后端协助添加响应头参数即可,以下以node.js为例

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "http://example.com");
  res.header("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
  res.header("Access-Control-Allow-Headers", "Content-Type");
  next();
});

优点:CORS是一种标准化的跨域解决方案,易于实现和配置,支持各种HTTP请求方法,实际开发也是此方法居多

缺点:需要服务器端支持CORS,不适用于旧版本的浏览器

3.代理服务器

实现原理:通过在同一域名下设置代理服务器,将前端的跨域请求转发到目标服务器上,从而绕过浏览器的同源策略限制。

简单来说,就是因为同源策略是建立在客户端浏览器和服务器上的,但是服务器与服务器之间是不受同源策略影响,所以就可以直接访问响应。

当我们需要请求一个地址为“https://www.example.com/api/data/list”的后端数据的时候,可以在vue.config.js中配置一个代理服务器(如果没有需要自己在最外层目录新建一个vue.config.js文件)

原本是

getData(){
		axios.get('https://www.example.com/api/data/list').then(res=>{
			console.log(res)
		})
}
// 此方法直接请求会导致跨域

现在按照如下配置vue.config.js

module.exports = {
    devServer:{
        proxy:{
            '/api':{        //表示会拦截以api为开头的请求
                target:'https://www.example.com/api',    //表示需要请求的目标url
                changeOrigin:true,    // 是否开启跨域
                pathRewrite:{        //重写路径
                    '^/api':''       //把/api开头的变为空
                }
            }
        }
    }
}

 并且把原本的发送请求修改为如下

// 发送请求
getData(){
    axios.get('api/data/list').then(res=>{
        console.log(res)
    })
}

 这样的话,请求就会先发送至代理服务器,然后通过代理服务器与目标服务器的交互,实现数据的传递。

优点:适用于所有浏览器,不需要服务器端额外配置。

缺点:需要额外的代理服务器配置和维护,增加了系统的复杂性。

以上就是目前主流的解决跨域问题(‘Access-Control-Allow-Origin’ missing)的常见方法,有其他疑问欢迎留言。