前端请求跨域问题

时间:2020-05-01

解释跨域

跨域资源共享(CORS) 是一种机制,它使用额外的 HTTP 头来告诉浏览器  让运行在一个 origin (domain) 上的Web应用被准许访问来自不同源服务器上的指定的资源。当一个资源从与该资源本身所在的服务器不同的域、协议或端口请求一个资源时,资源会发起一个跨域 HTTP 请求。 比如,站点 http://domain-a.com 的某 HTML 页面通过 <img> 的 src 请求 http://domain-b.com/image.jpg。网络上的许多页面都会加载来自不同域的CSS样式表,图像和脚本等资源。

出于安全原因,浏览器限制从脚本内发起的跨源HTTP请求。 例如,XMLHttpRequest和Fetch API遵循同源策略。 这意味着使用这些API的Web应用程序只能从加载应用程序的同一个域请求HTTP资源,除非响应报文包含了正确CORS响应头。

(译者注:这段描述不准确,并不一定是浏览器限制了发起跨站请求,也可能是跨站请求可以正常发起,但是返回结果被浏览器拦截了。)

出现跨域

后端测试代码

header('content-type:text/json;charset=utf-8');
$data = [
    'msg' => '',
    'data' => [
        'name' => 'wyzda',
        'age' => 28
    ],
    'status' => 1
];
echo json_encode($data);

后端访问链接:http://127.0.0.1/test/cos.php

打开浏览器是可以直接获取到数据的

但是用ajax请求就拿不了(如果前端与后端域名相同则不会出现跨域,不跨域就可以拿到后端返回数据的)

前端访问链接:http://localhost:63342/untitled/test.html

<script>
    let xml = new XMLHttpRequest();
    let url = 'http://127.0.0.1/test/cos.php';
    xml.open('GET',url);
    xml.onload = function (e) {
        console.log(e);
    }
    xml.send();
</script>

前端与后端域名不同会出现跨域,也就是前端拿不到后端数据,控制台报错。

Access to XMLHttpRequest at 'http://127.0.0.1/test/cos.php' from origin 'http://localhost:63342' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

报错说 No 'Access-Control-Allow-Origin' header  那就在后端加上。

header('Access-Control-Allow-Origin:*');

完整后端代码

header('content-type:text/json;charset=utf-8');
header('Access-Control-Allow-Origin:*');
$data = [
    'msg' => '',
    'data' => [
        'name' => 'wyzda',
        'age' => 28
    ],
    'status' => 1
];
echo json_encode($data);

再次请求发现没问题了。

出现跨域的几种情况

不同域名属于跨域,如:www.wyzda.com 和 www.baidu.com,另外www.wyzda.com 和www.wyzda.com.cn也属于不同域名

主域名和子域名(二级域名、三级域名等)跨域,如:www.wyzda.com 和 note.wyzda.com 跨域

不同协议属于跨域,如:http://www.wyzda.com 和 https://www.wyzda.com

ip和域名属于跨域,如:123.23.23.12 和 www.wyzda.com

还有一种情况也会出现跨域

自定义请求字段

如前端代码请求后端时带上一个token请求参数

xml.setRequestHeader('token','wyzda'); 

<script>
    let xml = new XMLHttpRequest();
    let url = 'http://127.0.0.1/test/cos.php';
    xml.open('GET',url);
    xml.onload = function (e) {
        console.log(e);
    }
    xml.setRequestHeader('token','wyzda');
    xml.send();
</script>
Access to XMLHttpRequest at 'http://127.0.0.1/test/cos.php' from origin 'http://localhost:63342' has been blocked by CORS policy: Request header field token is not allowed by Access-Control-Allow-Headers in preflight response.

 Request header field token is not allowed by Access-Control-Allow-Headers

那就在后端加上这个返回header呗

header('Access-Control-Allow-Headers:token');

完整后端代码

header('content-type:text/json;charset=utf-8');
header('Access-Control-Allow-Origin:*');
header('Access-Control-Allow-Headers:token');
$data = [
    'msg' => '',
    'data' => [
        'name' => 'wyzda',
        'age' => 28
    ],
    'status' => 1
];
echo json_encode($data);

出现跨域不要慌,主要看后端返回的header是否正确。