PHP/Nginx 跨域访问|逆浏览器请求之 JS 跨域访问

禁用跨域访问是浏览器保证安全访问的一项重要策略限制,很多跨域访问的操作都是违逆浏览器标准的。在一些场合不得不又需要用到,则本文大致说明下,在 Nginx 作为服务端是如何解决跨域访问。

参数解释

一些主要的跨域参数

Access-Control-Allow-origin # 授权允许来源
Access-Control-Allow-Methods # 授权允许方法
Access-Control-Allow-Headers # 授权允许请求头
Access-Control-Expose-Headers # 可公开响应头
Access-Control-Allow-Credentials # 允许认证 即开放 cookie

解释如下配置,允许 http://localhost:8080 整个来源进行访问。

Access-Control-Allow-Origin 支持 *,支持多个域名配置如:"http://localhost:8080,http://localhost:8081",用逗号进行隔开。

但此处因为有允许进行认证(授权 cookie),即 Origin 不支持 * 也不支持多个域名配置,仅支持单项域名配置。

Access-Control-Allow-Methods 允许 GET,POST,OPTIONS 请求访问,如果想要支持其他请求将其加入其中。OPTIONS 是预检请求,跨域中必须要将其开放。

Access-Control-Allow-Headers 允许客户端传递的 header 参数,如果客户端传递的 header 不在其中,则请求会失败。如需通过 Authorization 进行校验用户身份,则将 Authorization 配置到请求头。

同样,服务端如要返回其他响应头给客户端,也需指定,通过 Access-Control-Expose-Headers 配置,支持逗号隔开多个参数。

Access-Control-Allow-Credentials 允许授权 cookie,允许必须为 true,否则其它即禁用。

		add_header Access-Control-Allow-Origin "http://localhost:8080";
		add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
		add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
		add_header Access-Control-Expose-Headers 'Authorization';
		add_header Access-Control-Allow-Credentials 'true';

此操作安全极低,如需要可如下配置。

set $origin $http_origin;
if ( $origin = '' ) {
	set $origin "$scheme://$host:$server_port";
}
add_header Access-Control-Allow-Origin "$origin";

PHP 允许任意域名跨域

支持中间件的可以放置在中间件中,但 TP 的中间件存在问题,如访问的代码存在问题,会导致报错,也会导致代码执行不到中间件,也就无法让 option 预检测请求通过,即 TP 建议将代码放置 index.php

$origin = $_SERVER['HTTP_ORIGIN'] ?? '';
header('Access-Control-Allow-Origin: ' . $origin);
header('Access-Control-Allow-Headers: Authorization, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-Requested-With');
header('Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE');
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Max-Age: 1728000');
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
    return;
}

Comments