PHP允许跨域访问, HTTP设置跨域共享, 跨域资源共享 CORS 详解, Blocked by CORS policy: The ‘Access-Control-Allow-Origin’ – Mean Stack

跨域资源共享(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响应头。

 

PHP允许跨域访问, HTTP设置跨域共享, 跨域资源共享 CORS 详解, Blocked by CORS policy: The 'Access-Control-Allow-Origin' - Mean Stack
PHP允许跨域访问, HTTP设置跨域共享, 跨域资源共享 CORS 详解, Blocked by CORS policy: The ‘Access-Control-Allow-Origin’ – Mean Stack

跨域资源共享( CORS )机制允许 Web 应用服务器进行跨域访问控制,从而使跨域数据传输得以安全进行。现代浏览器支持在 API 容器中(例如 XMLHttpRequest 或 Fetch )使用 CORS,以降低跨域 HTTP 请求所带来的风险。

 

 

PHP上的CORS

如果您无权配置Apache,则仍然可以从PHP脚本发送标头。在您的PHP脚本中添加以下内容是一种情况:

<?php
header("Access-Control-Allow-Origin: *");
注意:与PHP 标头函数的所有用法一样,此操作必须在从服务器发送任何输出之前进行。

请注意,这实际上会禁用CORS保护,并使您的用户容易受到攻击。如果不确定您是否需要允许所有起源,则应将其锁定为更特定的起源:

<?php
header('Access-Control-Allow-Origin: https://www.example.com')

 

如果您希望Access-Control-Allow-Origin为允许的每个站点发送多个标,那不幸的是,官方不支持发送多个Access-Control-Allow-Origin标头或放入多个来源。

您可以通过以下方法解决此问题:检查原点,然后在标头中发回该原点(如果允许):

$origin = $_SERVER['HTTP_ORIGIN'];
$allowed_domains = [
    'http://mysite1.com',
    'https://www.mysite2.com',
    'http://www.mysite2.com',
];

if (in_array($origin, $allowed_domains)) {
    header('Access-Control-Allow-Origin: ' . $origin);
}

那更安全。您可能需要编辑匹配项,并使用一些正则表达式或类似的东西将其更改为手动功能。至少这只会发送回1标头,并且您可以确定它是请求来自的标头。请注意,所有HTTP标头都可以被欺骗,但是此标头是为了保护客户端。不要用这些值保护您自己的数据。如果您想了解更多信息,请阅读有关CORS和CSRF的内容。

 

为什么更安全?

允许从其他位置访问,则您自己的受信任站点允许会话劫持。我将举一个小例子-图像Facebook允许使用通配符起源-这意味着您可以在某个地方创建自己的网站,并将其触发对Facebook的AJAX调用(或打开iframe)。这意味着您可以获取您网站访问者的Facebook登录信息。更糟糕的是,您可以POST在他人浏览您的网站时编写请求脚本并将数据发布到某人的Facebook上。

使用ACAO接头时要非常小心!

 

 

 

跨域资源共享 CORS 详解

 

CORS(Cross-origin resource sharing) “跨域资源共享”

在出现CORS标准之前, 我们还只能通过jsonp(jsonp跨域请求详解)的形式去向“跨源”服务器去发送 XMLHttpRequest 请求,这种方式吃力不讨好,在请求方与接收方都需要做处理,而且请求的方式仅仅局限于GET。所以 ,CORS标准必然是大势所趋,并且市场上绝大多数浏览器都已经支持CORS。(IE10以上)

 

CORS概念

支持CORS请求的浏览器一旦发现ajax请求跨域,会对请求做一些特殊处理,对于已经实现CORS接口的服务端,接受请求,并做出回应。

有一种情况比较特殊,如果我们发送的跨域请求为“非简单请求”,浏览器会在发出此请求之前首先发送一个请求类型为OPTIONS的“预检请求”,验证请求源是否为服务端允许源,这些对于开发这来说是感觉不到的,由浏览器代理。

总而言之,客户端不需要对跨域请求做任何特殊处理。

 

简单请求与非简单请求

浏览器对跨域请求区分为“简单请求”与“非简单请求”

“简单请求”满足以下特征:

  • 请求方法是以下三种方法之一:
    HEAD
    GET
    POST

     

  • HTTP的头信息不超出以下几种字段:
    Accept
    Accept-Language
    Content-Language
    Last-Event-ID
    Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

     


不满足这些特征的请求称为“非简单请求”,例如:content-type=applicaiton/json , method = PUT/DELETE…

Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4,pt;q=0.2,fr;q=0.2
Cache-Control:no-cache
Connection:keep-alive
Host:b.code.com:8080
Origin:http://a.code.com:8080
Pragma:no-cache
Referer:http://a.code.com:8080/
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36

以上会出现本次请求来自哪个源(协议 + 域名 + 端口),
Origin 指定的源,不在许可范围内,服务器会返回一个正常的HTTP回应。

Connection:keep-alive
Content-Length:430
Content-Type:application/json; charset=utf-8
Date:Tue, 25 Apr 2017 14:08:44 GMT
ETag:W/"1ae-VP1n2Jqobg5OeVKZa52pn4FP1/k"
X-Powered-By:Express

 

Response Headers 没有包含 Access-Control-Allow-Origin 字段,
服务器抛出XMLHttpRequest不能加载的错误

XMLHttpRequest cannot load http://b.code.com:8080/getNews. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://a.code.com:8080' is therefore not allowed access.

 

简单请求

浏览器判断跨域为简单请求时候,会在Request Header中添加 Origin (协议 + 域名 + 端口)字段 , 它表示我们的请求源,CORS服务端会将该字段作为跨源标志。

PHP允许跨域访问, HTTP设置跨域共享, 跨域资源共享 CORS 详解, Blocked by CORS policy: The 'Access-Control-Allow-Origin' - Mean Stack
PHP允许跨域访问, HTTP设置跨域共享, 跨域资源共享 CORS 详解, Blocked by CORS policy: The ‘Access-Control-Allow-Origin’ – Mean Stack

 

CORS接收到此次请求后 , 首先会判断Origin是否在允许源(由服务端决定)范围之内,如果验证通过,服务端会在Response Header 添加 Access-Control-Allow-Origin、Access-Control-Allow-Credentials等字段。

 

PHP允许跨域访问, HTTP设置跨域共享, 跨域资源共享 CORS 详解, Blocked by CORS policy: The 'Access-Control-Allow-Origin' - Mean Stack
PHP允许跨域访问, HTTP设置跨域共享, 跨域资源共享 CORS 详解, Blocked by CORS policy: The ‘Access-Control-Allow-Origin’ – Mean Stack

 

必须字段:
Access-Control-Allow-Origin:表示服务端允许的请求源,*标识任何外域,多个源 , 分隔 

可选字段 
Access-Control-Allow-Credentials:false 表示是否允许发送Cookie,设置为true 同时,ajax请求设置withCredentials = true,浏览器的cookie就能发送到服务端
 Access-Control-Expose-Headers:调用getResponseHeader()方法时候,能从header中获 取的参数

 

浏览器收到Respnose后会判断自己的源是否存在 Access-Control-Allow-Origin允许源中,如果不存在,会抛出“同源检测异常”。

总结:简单请求只需要CORS服务端在接受到携带Origin字段的跨域请求后,在response header中添加Access-Control-Allow-Origin等字段给浏览器做同源判断。

 

PHP允许跨域访问, HTTP设置跨域共享, 跨域资源共享 CORS 详解, Blocked by CORS policy: The 'Access-Control-Allow-Origin' - Mean Stack
PHP允许跨域访问, HTTP设置跨域共享, 跨域资源共享 CORS 详解, Blocked by CORS policy: The ‘Access-Control-Allow-Origin’ – Mean Stack

 

非简单请求

进行非简单请求时候 , 浏览器会首先发出类型为OPTIONS的“预检请求”,请求地址相同 ,
CORS服务端对“预检请求”处理,并对Response Header添加验证字段,客户端接受到预检请求的返回值进行一次请求预判断,验证通过后,主请求发起。

例如:发起 content-type=application/json 的非简单请求,这时候传参要注意为json字符串

PHP允许跨域访问, HTTP设置跨域共享, 跨域资源共享 CORS 详解, Blocked by CORS policy: The 'Access-Control-Allow-Origin' - Mean Stack
PHP允许跨域访问, HTTP设置跨域共享, 跨域资源共享 CORS 详解, Blocked by CORS policy: The ‘Access-Control-Allow-Origin’ – Mean Stack

 

这里可以看到,浏览器连续发送了两个jsonp.do请求 , 第一个就是“预检请求”,类型为OPTIONS,因为我们设置了content-type这个属性,所以预检请求的Access-Control-Expose-Headers必须携带content-type,否则预检会失败。

预检通过后,主请求与简单请求一致。

总结:非简单请求需要CORS服务端对OPTIONS类型的请求做处理,其他与简单请求一致

 

PHP允许跨域访问, HTTP设置跨域共享, 跨域资源共享 CORS 详解, Blocked by CORS policy: The 'Access-Control-Allow-Origin' - Mean Stack
PHP允许跨域访问, HTTP设置跨域共享, 跨域资源共享 CORS 详解, Blocked by CORS policy: The ‘Access-Control-Allow-Origin’ – Mean Stack

 

Spring MVC CORS

通过上面叙述,我们得知借助CORS我们不必关心发出的请求是否跨域,浏览器会帮我们处理这些事情,但是服务端需要支持CORS,服务端实现CORS的原理也很简单,在服务端完全可以对请求做上下文处理,已达到接口允许跨域访问的目的。

 

当然,也有很多第三方的CORS插件,例如:Spring MVC 在4.2以上版本也支持了CORS配置,这样,服务端也无需自己操心了!

 

 

本文:PHP允许跨域访问, HTTP设置跨域共享, 跨域资源共享 CORS 详解, Blocked by CORS policy: The ‘Access-Control-Allow-Origin’ – Mean Stack

Leave a Reply