diff options
Diffstat (limited to 'files/zh-cn/web/http/server-side_access_control/index.html')
-rw-r--r-- | files/zh-cn/web/http/server-side_access_control/index.html | 249 |
1 files changed, 0 insertions, 249 deletions
diff --git a/files/zh-cn/web/http/server-side_access_control/index.html b/files/zh-cn/web/http/server-side_access_control/index.html deleted file mode 100644 index 50a52b3405..0000000000 --- a/files/zh-cn/web/http/server-side_access_control/index.html +++ /dev/null @@ -1,249 +0,0 @@ ---- -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 ---- -<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"><?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>"; -} -?> -</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"><?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"); - -?> -</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"><?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"); - - - -?> -</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> |