跨域资源共享(CORS)

Cross-Origin Resource Sharing(CORS)跨域资源共享是一份浏览器技术的规范,它允许浏览器向跨源(协议 + 域名 + 端口)服务器,发出XMLHttpRequest请求,从而避开了浏览器的同源策略,是 JSONP 模式的现代版。

CORS需要浏览器和服务器同时支持。但主要都是服务器端的配置,都是设置一系列的响应头 (Response Headers)。

Access-Control-Allow-Origin:  http://www.YOURDOMAIN.com             // 设置允许请求的域名,多个域名以逗号分隔

Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS       // 设置允许请求的方法,多个方法以逗号分隔

Access-Control-Allow-Headers: Authorization                         // 设置允许请求自定义的请求头字段,多个字段以逗号分隔

Access-Control-Allow-Credentials: true                              // 设置是否允许发送 Cookies

基本流程

浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。
浏览器发出CORS简单请求,只需要在头信息之中增加一个Origin字段。
浏览器发出CORS非简单请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。

只要同时满足以下两大条件,就属于简单请求。
1) 请求方法是以下三种方法之一:
HEAD
GET
POST
2)HTTP的头信息不超出以下几种字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

实现方式:

1、ajax + PHP为例:

后台:

<?php
        header('Access-Control-Allow-Origin: http://www.YOURDOMAIN.com');

        header('Access-Control-Allow-Credentials: true');                           //可选

        header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');

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


        // 判断如果是 OPTIONS 请求,直接退出即可
        if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') { 
            exit;
        }

        echo json_encode(array('status' => '1', 'data' => ''));
   ?>

前端:

$.ajax({
        url: aURL,
        type: aMethod,
        data: aParams,
        dataType: 'json',
        timeout: 1000 * 120,
        beforeSend: function (xhr) {
            var token = $.cookie('token');
            if (token) {
                xhr.setRequestHeader('Authorization', 'Bearer ' + token);
            }
        },
        success: function (response) {
            if (response.code == 200) {
                typeof aSuccess == 'function' && aSuccess(response.data);
            } else {
                typeof aError == 'function' && aError(response.message);
            }
        },
        error: function(xhr, type){
            typeof aError == 'function' && aError(xhr.status + ' '  + xhr.statusText);
        }
    });

2、原生js + node.js 为例:

后台:

if (req.headers.origin) {

            res.writeHead(200, {
                "Content-Type": "text/html; charset=UTF-8",
                "Access-Control-Allow-Origin":'http://localhost'/*,
                'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
                'Access-Control-Allow-Headers': 'X-Requested-With, Content-Type'*/
            });
            res.write('cors');
            res.end();
        }

前端:

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
    <title>jsonp_test</title>

    <script>
      /*var f = function(data){
        alert(data.name);
      }*/
      var xhr = new XMLHttpRequest();
      xhr.onload = function(){
        alert(xhr.responseText);
      };
      xhr.open('POST', 'http://localhost:8888/cors', true);
      xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
      xhr.send("f=json");
    </script>
    
    <script>
     /* var _script = document.createElement('script');
      _script.type = "text/javascript";
      _script.src = "http://localhost:8888/jsonp?callback=f";
      document.head.appendChild(_script);*/
    </script>
  </head>
  
  <body>
  </body>
</html>

**参考文献:** 1、[HTTP访问控制(CORS)](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS) 2、[AJAX 跨域 CORS 解决方案](https://www.cnblogs.com/xinpureZhu/p/5783250.html) 3、[CORS(跨域资源共享)](https://www.cnblogs.com/cityspace/p/6858969.html) 4、[探讨跨域请求资源的几种方式](https://www.cnblogs.com/dojo-lzz/p/4265637.html)
Last modification:November 12, 2018
If you think my article is useful to you, please feel free to appreciate