复杂请求的跨域解决方法

简单请求遇到跨域问题时,只需要在服务器端设置响应头中加入允许跨域的头部信息即可。

当遇到复杂请求时,浏览器为了防止跨域请求无端对服务器数据造成损坏会先发送一个 Options 的预检请求。服务器应该对其进行处理,决定是否允许当前客户端进一步发起跨域请求。随后浏览器会根据 Options 请求的响应信息来决定是否进行下一步真实的请求。

服务器在此次 Options 请求的返回内容中还可以指示浏览器,是否在下次请求携带相关的 Cookie 或者 Http Authentication 数据过来。

什么是简单请求

  1. 仅使用 Get 方法的请求。
  2. 仅使用 Head 方法的请求。
  3. 仅使用 Content-Type 为 application/x-www-form-urlencoded、multipart/form-data 或 text/plain 发起的 Post 请求。

什么是复杂请求

不满足简单请求条件的都属于复杂请求。

解决复杂请求下的跨域问题

 1<?php
 2
 3class CORSMiddleware
 4{
 5    public function handle($request, Closure $next)
 6    {
 7        // 跨域请求时浏览器会先使用 options 方法判断是否允许当前域名发送跨域请求
 8        $origin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : '';
 9
10        $allow_origin = array(
11            'http://localhost:8888',
12            'http://test.com',
13            'https://test.com',
14        );
15
16        // 如果请求方法为 options, 加入允许跨域响应头并直接发送响应信息
17        if ($request->isMethod('options') && in_array($origin, $allow_origin)) {
18            header("Access-Control-Allow-Methods: POST, GET, PATCH, PUT, DELETE");
19            header("Access-Control-Allow-Origin:".$origin);
20            header("Access-Control-Allow-Headers: Content-Type, X-Auth-Token, Origin");
21            header("Access-Control-Allow-Credentials: true");
22
23            return response('OK', '200');
24        }
25
26        if (in_array($origin, $allow_origin)) {
27            header("Access-Control-Allow-Methods: POST, GET, PATCH, PUT, DELETE");
28            header("Access-Control-Allow-Origin:".$origin);
29            header("Access-Control-Allow-Headers: Content-Type, X-Auth-Token, Origin");
30            header("Access-Control-Allow-Credentials: true");
31        }
32
33        return $next($request);
34    }
35}

参考 & 扩展阅读