From 310fd066e91f454b990372ffa30e803cc8120975 Mon Sep 17 00:00:00 2001 From: Florian Merz Date: Thu, 11 Feb 2021 12:56:40 +0100 Subject: unslug zh-cn: move --- files/zh-cn/conflicting/web/http/cors/index.html | 249 +++++++++++++++++++++++ 1 file changed, 249 insertions(+) create mode 100644 files/zh-cn/conflicting/web/http/cors/index.html (limited to 'files/zh-cn/conflicting/web/http/cors') diff --git a/files/zh-cn/conflicting/web/http/cors/index.html b/files/zh-cn/conflicting/web/http/cors/index.html new file mode 100644 index 0000000000..50a52b3405 --- /dev/null +++ b/files/zh-cn/conflicting/web/http/cors/index.html @@ -0,0 +1,249 @@ +--- +title: Server-Side Access Control +slug: Web/HTTP/Server-Side_Access_Control +tags: + - AJAX + - CORS + - HTTP + - PHP +translation_of: Web/HTTP/CORS +translation_of_original: Web/HTTP/Server-Side_Access_Control +--- +

{{HTTPSidebar}}

+ +

浏览器会针对从 {{domxref("XMLHttpRequest")}} 或Fetch API中发起的跨网站请求发送特定的HTTP标头。它还希望看到使用跨站点响应发送回的特定HTTP标头。这些标头的概述,包括启动请求和处理来自服务器的响应的示例JavaScript代码, 以及每个头的讨论,可以在HTTP访问控制(CORS)文章中找到,应该作为本文的配套文章阅读。

+ +

HTTP访问控制文章是很好的使用指南。本文介绍利用PHP处理访问控制请求和制定访问控制响应。本文的目标读者是服务器程序员或管理员。虽然在PHP代码示例所示,类似的概念适用于ASP.net,Perl、Python、Java等;一般来说,这些概念可以应用于任何服务器端编程环境处理HTTP请求和动态制定的HTTP响应。

+ +

讨论HTTP标头

+ +

了解HTTP 头部信息, 建议先阅读这篇文章 covering the HTTP headers used by both clients (such as Firefox 3.5 and beyond) and servers

+ +
 
+ +

工作代码示例

+ +

随后的章节中PHP代码(和JavaScript调用服务器)可查看相关代码,这些代码在实现了XMLHttpRequest的浏览器上都可运行,像Firefox 3.5及以上。

+ +
 
+ +

简单的跨站请求

+ +

简单的访问控制请求 在下列情况下会被发起:

+ + + +

以下情况,请求会返回相关响应信息

+ + + +

 简单的访问控制请求 介绍了在客户端和服务端进行信息交换的HEADER.  下面是一段用来处理简单请求的PHP代码。

+ +
<?php
+
+// 我们将只授予 arunranga.com 域的访问权限,因为我们认为它通过 application/xml 方式来访问这些资源是安全的。
+
+if($_SERVER['HTTP_ORIGIN'] == "http://arunranga.com")
+{
+
+    header('Access-Control-Allow-Origin: http://arunranga.com');
+    header('Content-type: application/xml');
+    readfile('arunerDotNetResource.xml');
+}
+else
+{
+header('Content-Type: text/html');
+echo "<html>";
+echo "<head>";
+echo "   <title>Another Resource</title>";
+echo "</head>";
+echo "<body>",
+    "<p>This resource behaves two-fold:";
+echo "<ul>",
+        "<li>If accessed from <code>http://arunranga.com</code> it returns an XML document</li>";
+echo " <li>If accessed from any other origin including from simply typing in the URL into the browser's address bar,";
+echo "you get this HTML document</li>",
+    "</ul>",
+"</body>",
+"</html>";
+}
+?>
+
+ +

上面的代码通过检查浏览器发送的 ORIGIN 头部信息(通过 $_SERVER['HTTP_ORIGIN'] ) 是否匹配 'http://arunranga.com' 得知,如果是,返回 Access-Control-Allow-Origin: http://arunranga.com 。如果你的浏览器支持访问控制,你可以访问 这里 .

+ +

预请求

+ +

预请求 发生在下列情况中:

+ + + +

预请求访问控制 这篇文章介绍了在客户端和服务器间进行交换的头信息,响应preflight requests请求的服务器资源会有这些动作:

+ + + +

下面是相关的PHP内容, preflighted request:

+ +
<?php
+if($_SERVER['REQUEST_METHOD'] == "GET")
+{
+    header('Content-Type: text/plain');
+    echo "This HTTP resource is designed to handle POSTed XML input from arunranga.com and not be retrieved with GET";
+
+}
+elseif($_SERVER['REQUEST_METHOD'] == "OPTIONS")
+{
+    // 告诉客户端我们支持来自 arunranga.com 的请求并且预请求有效期将仅有20天
+    if($_SERVER['HTTP_ORIGIN'] == "http://arunranga.com")
+    {
+    header('Access-Control-Allow-Origin: http://arunranga.com');
+    header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
+    header('Access-Control-Allow-Headers: X-PINGARUNER');
+    header('Access-Control-Max-Age: 1728000');
+    header("Content-Length: 0");
+    header("Content-Type: text/plain");
+    //exit(0);
+    }
+    else
+    {
+    header("HTTP/1.1 403 Access Forbidden");
+    header("Content-Type: text/plain");
+    echo "You cannot repeat this request";
+
+    }
+}
+elseif($_SERVER['REQUEST_METHOD'] == "POST")
+{
+    /* 通过首先获得XML传送过来的blob来处理POST请求,然后做一些处理, 最后将结果返回客户端
+    */
+    if($_SERVER['HTTP_ORIGIN'] == "http://arunranga.com")
+    {
+            $postData = file_get_contents('php://input');
+            $document = simplexml_load_string($postData);
+
+            // 对POST过来的数据进行一些处理
+
+            $ping = $_SERVER['HTTP_X_PINGARUNER'];
+
+
+            header('Access-Control-Allow-Origin: http://arunranga.com');
+            header('Content-Type: text/plain');
+            echo // 处理之后的一些响应
+    }
+    else
+        die("POSTing Only Allowed from arunranga.com");
+}
+else
+    die("No Other Methods Allowed");
+
+?>
+
+ +

可以看到,就像POST一样,针对OPTIONS preflight请求,同样返回对应的头信息。这样 以来,处理preflight就像处理普通的request请求一样,在针对OPTIONS请求的响应信息中,服务器通过客户端,实际的请求可以用POST的形式发送,同时可附加X-PINGARUNERP这样的头信息。如果浏览器支持的话,可访问 这里

+ +

凭证请求

+ +

带凭据的请求,将Cookies和HTTP认证信息一起发送出去的跨域请求,根据请求方式,可以是 Simple 或 Preflighted,

+ +

发送 简单请求 时, Firefox 3.5 (或以上)会发送带Cookies信息的请求,  (如果withCredentials 设以true). 如果服务器响应真的是可信任的, 客户端接受并进行输出。 在 预请求 中,服务器可以针对 OPTIONS 请求,返回 Access-Control-Allow-Credentials: true 信息

+ +

下面是处理请求的PHP内容:

+ +
<?php
+
+if($_SERVER['REQUEST_METHOD'] == "GET")
+{
+
+    // First See if There Is a Cookie
+    //$pageAccess = $_COOKIE['pageAccess'];
+    if (!isset($_COOKIE["pageAccess"])) {
+
+    setcookie("pageAccess", 1, time()+2592000);
+    header('Access-Control-Allow-Origin: http://arunranga.com');
+    header('Cache-Control: no-cache');
+    header('Pragma: no-cache');
+    header('Access-Control-Allow-Credentials: true');
+    header('Content-Type: text/plain');
+    echo 'I do not know you or anyone like you so I am going to mark you with a Cookie :-)';
+
+    }
+    else
+    {
+
+    $accesses = $_COOKIE['pageAccess'];
+    setcookie('pageAccess', ++$accesses, time()+2592000);
+    header('Access-Control-Allow-Origin: http://arunranga.com');
+    header('Access-Control-Allow-Credentials: true');
+    header('Cache-Control: no-cache');
+    header('Pragma: no-cache');
+    header('Content-Type: text/plain');
+    echo 'Hello -- I know you or something a lot like you!  You have been to ', $_SERVER['SERVER_NAME'], ' at least ', $accesses-1, ' time(s) before!';
+    }
+
+}
+elseif($_SERVER['REQUEST_METHOD'] == "OPTIONS")
+{
+    // Tell the Client this preflight holds good for only 20 days
+    if($_SERVER['HTTP_ORIGIN'] == "http://arunranga.com")
+    {
+    header('Access-Control-Allow-Origin: http://arunranga.com');
+    header('Access-Control-Allow-Methods: GET, OPTIONS');
+    header('Access-Control-Allow-Credentials: true');
+    header('Access-Control-Max-Age: 1728000');
+    header("Content-Length: 0");
+    header("Content-Type: text/plain");
+    //exit(0);
+    }
+    else
+    {
+    header("HTTP/1.1 403 Access Forbidden");
+    header("Content-Type: text/plain");
+    echo "You cannot repeat this request";
+
+    }
+}
+else
+    die("This HTTP Resource can ONLY be accessed with GET or OPTIONS");
+
+
+
+?>
+
+ +

需要注意的是,在带凭据请求中, Access-Control-Allow-Origin: 头不能是通配符 "*",必须是一个有效的域名。  可参考这里 running here

+ +

Apache示例

+ +

限制对某些URI的访问

+ +

最有效的方法之一,利用Apache rewrite, 环境变量,还有headers使Access-Control-Allow-* 对某些特定的URI生效,比如,以无认证信息形式利用GET跨域请求api(.*).json。

+ +
RewriteRule ^/api(.*)\.json$ /api$1.json [CORS=True]
+Header set Access-Control-Allow-Origin "*" env=CORS
+Header set Access-Control-Allow-Methods "GET" env=CORS
+Header set Access-Control-Allow-Credentials "false" env=CORS
+
+ +

参见

+ + -- cgit v1.2.3-54-g00ecf