aboutsummaryrefslogtreecommitdiff
path: root/files/zh-cn/conflicting/web/http/cors/index.html
diff options
context:
space:
mode:
Diffstat (limited to 'files/zh-cn/conflicting/web/http/cors/index.html')
-rw-r--r--files/zh-cn/conflicting/web/http/cors/index.html250
1 files changed, 250 insertions, 0 deletions
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..eb37a40e1d
--- /dev/null
+++ b/files/zh-cn/conflicting/web/http/cors/index.html
@@ -0,0 +1,250 @@
+---
+title: Server-Side Access Control
+slug: conflicting/Web/HTTP/CORS
+tags:
+ - AJAX
+ - CORS
+ - HTTP
+ - PHP
+translation_of: Web/HTTP/CORS
+translation_of_original: Web/HTTP/Server-Side_Access_Control
+original_slug: Web/HTTP/Server-Side_Access_Control
+---
+<p>{{HTTPSidebar}}</p>
+
+<p>浏览器会针对从 {{domxref("XMLHttpRequest")}} 或<a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API">Fetch API</a>中发起的跨网站请求发送特定的<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers">HTTP标头</a>。它还希望看到使用跨站点响应发送回的特定HTTP标头。这些标头的概述,包括启动请求和处理来自服务器的响应的示例JavaScript代码, 以及每个头的讨论,可以在HTTP访问控制(<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS">CORS</a>)文章中找到,应该作为本文的配套文章阅读。</p>
+
+<p>HTTP访问控制文章是很好的使用指南。本文介绍利用PHP处理访问控制请求和制定访问控制响应。本文的目标读者是服务器程序员或管理员。虽然在PHP代码示例所示,类似的概念适用于ASP.net,Perl、Python、Java等;一般来说,这些概念可以应用于任何服务器端编程环境处理HTTP请求和动态制定的HTTP响应。</p>
+
+<h3 id="讨论HTTP标头"><strong>讨论HTTP标头</strong></h3>
+
+<p>了解HTTP 头部信息, 建议先阅读这篇文章 <a href="https://developer.mozilla.org/En/HTTP_access_control">covering the HTTP headers used by both clients (such as Firefox 3.5 and beyond) and servers</a></p>
+
+<div> </div>
+
+<h3 id="工作代码示例"><strong>工作代码示例</strong></h3>
+
+<p>随后的章节中PHP代码(和JavaScript调用服务器)可查看<a href="http://arunranga.com/examples/access-control/">相关代码</a>,这些代码在实现了XMLHttpRequest的浏览器上都可运行,像Firefox 3.5及以上。</p>
+
+<div> </div>
+
+<h3 id="简单的跨站请求"><strong>简单的跨站请求</strong></h3>
+
+<p><a class="internal" href="/En/HTTP_access_control#Simple_requests" title="En/HTTP access control#Simple requests">简单的访问控制请求</a> 在下列情况下会被发起:</p>
+
+<ul>
+ <li>请求方式为 HTTP/1.1 <code style="font-style: normal;">GET </code>或者<code style="font-style: normal;"> POST</code>,如果是<code style="font-style: normal;">POST</code>,则请求的Content-Type为以下之一: <code style="font-style: normal;">application/x-www-form-urlencoded</code>, <code style="font-style: normal;">multipart/form-data</code>, 或<code style="font-style: normal;">text/plain</code></li>
+ <li>在请求中,不会发送自定义的头部(如X-Modified)</li>
+</ul>
+
+<p>以下情况,请求会返回相关响应信息</p>
+
+<ul>
+ <li>如果资源是允许公开访问的(就像任何允许GET访问的 HTTP资源),返回Access-Control-Allow-Origin:*头信息就足够了,除非是一些需要Cookies和HTTP身份验证信息的请求。</li>
+ <li>
+ <div class="tran-result">如果资源访问被限制基于相同的域名,或者如果要访问的资源需要凭证(或设置凭证),那么就有必要对请求头信息中的ORIGIN进行过滤,或者至少响应请求的来源(例如Access-Control-Allow-Origin:http://arunranga.com)。另外,将发送Access-Control-Allow-Credentials:TRUE头信息,这在后续部分将进行讨论。</div>
+ </li>
+</ul>
+
+<p> <a class="internal" href="/En/HTTP_access_control#Simple_requests" title="En/HTTP access control#Simple requests">简单的访问控制请求</a> 介绍了在客户端和服务端进行信息交换的HEADER.  下面是一段用来处理简单请求的PHP代码。</p>
+
+<pre class="brush: php">&lt;?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 "&lt;html&gt;";
+echo "&lt;head&gt;";
+echo " &lt;title&gt;Another Resource&lt;/title&gt;";
+echo "&lt;/head&gt;";
+echo "&lt;body&gt;",
+ "&lt;p&gt;This resource behaves two-fold:";
+echo "&lt;ul&gt;",
+ "&lt;li&gt;If accessed from &lt;code&gt;http://arunranga.com&lt;/code&gt; it returns an XML document&lt;/li&gt;";
+echo " &lt;li&gt;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&lt;/li&gt;",
+ "&lt;/ul&gt;",
+"&lt;/body&gt;",
+"&lt;/html&gt;";
+}
+?&gt;
+</pre>
+
+<p>上面的代码通过检查浏览器发送的 <code>ORIGIN</code> 头部信息(通过<code> $_SERVER['HTTP_ORIGIN']</code> ) 是否匹配 '<a class="external" href="http://arunranga.com" rel="freelink" style="font-size: 14px; line-height: 1.5;">http://arunranga.com</a>' 得知,如果是,返回 Access-Control-Allow-Origin: <a class="external" href="http://arunranga.com" rel="freelink" style='font-size: 14px; line-height: 1.5; font-family: "Courier New","Andale Mono",monospace;'>http://arunranga.com</a> 。如果你的浏览器支持访问控制<span style="font-size: 14px; line-height: 1.5;">,你可以访问 <a class="external" href="http://arunranga.com/examples/access-control/" style="font-size: 14px; line-height: 1.5;" title="http://arunranga.com/examples/access-control/">这里 .</a></span></p>
+
+<h3 id="预请求"><strong>预请求</strong></h3>
+
+<p><a class="internal" href="/En/HTTP_access_control#Preflighted_requests" title="En/HTTP access control#Preflighted requests">预请求</a> 发生在下列情况中:</p>
+
+<ul>
+ <li>使用GET或POST以外的方法;利用POST发送<code style="font-style: normal;">application/x-www-form-urlencoded</code>, <code style="font-style: normal;">multipart/form-data</code>, or <code style="font-style: normal;">text/plain</code>之外的Content-Type;例如,post body的Content-type为<code style="font-style: normal;">application/xml</code></li>
+ <li>发送自定义的头信息,如x-pingaruner</li>
+</ul>
+
+<p><a class="internal" href="/En/HTTP_access_control#Preflighted_requests" title="En/HTTP access control#Preflighted requests">预请求访问控制</a> 这篇文章介绍了在客户端和服务器间进行交换的<span style="font-size: 14px; line-height: 1.5;">头信息,响应preflight requests请求的服务器资源会有这些动作:</span></p>
+
+<ul>
+ <li> 基于 <code>ORIGIN </code>进行过滤</li>
+ <li> preflight请求的响应内容,包括必要的 <code>Access-Control-Allow-Methods</code>, <code>Access-Control-Allow-Headers</code> (保证系统正常运行),如果需要凭据的话,也会包括 <code>Access-Control-Allow-Credentials </code>头信息</li>
+ <li>响应实际请求,包括处理 POST数据等。</li>
+</ul>
+
+<p>下面是相关的PHP内容, <a class="internal" href="/En/HTTP_access_control#Preflighted_requests" title="En/HTTP access control#Preflighted requests">preflighted request</a>:</p>
+
+<pre class="brush: php">&lt;?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");
+
+?&gt;
+</pre>
+
+<p>可以看到,就像POST一样,针对OPTIONS preflight请求,同样返回对应的头信息。这样 以来,处理preflight就像处理普通的request请求一样,在针对OPTIONS请求的响应信息中,服务器通过客户端,实际的请求可以用POST的形式发送,同时可附加X-PINGARUNERP这样的头信息。如果浏览器支持的话,可访问<a class="external" href="http://arunranga.com/examples/access-control/" style="line-height: 1.5;" title="http://arunranga.com/examples/access-control/"> 这里</a></p>
+
+<h3 id="凭证请求"><strong>凭证请求</strong></h3>
+
+<p>带凭据的请求,将Cookies和HTTP认证信息一起发送出去的跨域请求,根据请求方式,可以是<span style="line-height: 1.5;"> </span><a class="internal" href="/En/HTTP_access_control#Simple_requests" style="line-height: 1.5;" title="En/HTTP access control#Simple requests">Simple</a><span style="line-height: 1.5;"> 或 </span><a class="internal" href="/En/HTTP_access_control#Preflighted_requests" style="line-height: 1.5;" title="En/HTTP access control#Preflighted requests">Preflighted</a><span style="line-height: 1.5;">,</span></p>
+
+<p>发送 <a class="internal" href="/En/HTTP_access_control#Simple%20requests" title="En/HTTP access control#Simple requests">简单请求</a> 时, Firefox 3.5 (或以上)会发送带Cookies信息的请求,  (如果<code>withCredentials</code> 设以true). 如果服务器响应真的是可信任的, 客户端接受并进行输出。 在 <a class="internal" href="/En/HTTP_access_control#Preflighted%20requests" title="En/HTTP access control#Preflighted requests">预请求</a> 中,服务器可以<span style="line-height: 1.5;">针对</span><span style="line-height: 1.5;"> </span><code style="font-style: normal; line-height: 1.5;">OPTIONS</code><span style="line-height: 1.5;"> 请求,返回</span><span style="line-height: 1.5;"> </span><code style="font-style: normal; line-height: 1.5;">Access-Control-Allow-Credentials: true</code><span style="line-height: 1.5;"> 信息</span></p>
+
+<p>下面是处理请求的PHP内容:</p>
+
+<pre class="brush: php">&lt;?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");
+
+
+
+?&gt;
+</pre>
+
+<p>需要注意的是,在带凭据请求中, <code>Access-Control-Allow-Origin:</code> 头不能是通配符 "*",必须是一个有效的域名。  可参考这里 <a class="external" href="http://arunranga.com/examples/access-control/" title="http://arunranga.com/examples/access-control/">running here</a></p>
+
+<h3 id="Apache示例"><strong>Apache示例</strong></h3>
+
+<h4 id="限制对某些URI的访问"><strong>限制对某些URI的访问</strong></h4>
+
+<p>最有效的方法之一,利用Apache rewrite, 环境变量,还有headers使<code style="font-style: normal; line-height: 1.5;">Access-Control-Allow-*</code><span style="line-height: 1.5;"> 对某些特定的URI生效,比如,以无认证信息形式利用GET跨域请求api(.*).json。</span></p>
+
+<pre>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
+</pre>
+
+<h3 id="参见"><strong>参见</strong></h3>
+
+<ul>
+ <li><a class="external" href="http://arunranga.com/examples/access-control/" title="http://arunranga.com/examples/access-control/">Examples of Access Control in Action</a></li>
+ <li><a class="internal" href="/En/HTTP_access_control" title="En/HTTP Access Control">HTTP Access Control covering the HTTP Headers</a></li>
+ <li><a class="internal" href="/en/DOM/XMLHttpRequest" title="En/XMLHttpRequest">XMLHttpRequest</a></li>
+ <li><a class="external" href="http://www.webfonts.info/wiki/index.php?title=%40font-face_support_in_Firefox" title="http://www.webfonts.info/wiki/index.php?title=@font-face_support_in_Firefox">Web Fonts</a></li>
+</ul>