Firefox 3.5 implements the W3C Access Control specification.  As a result, Firefox 3.5 sends specific HTTP headers for cross-site requests initiated from withinXMLHttpRequest (which in Firefox 3.5 and beyond can be used to invoke different domains) and for cross-site font downloads.  It also expects to see specific HTTP headers sent back with cross-site responses.  An overview of these headers, including sample JavaScript code that initiates requests and processes responses from the server, as well as a discussion of each header, can be found here (HTTP Access Control).  The HTTP Access Control article should be read as a companion article to this one.  This article covers processing Access Control Requests and formulating Access Control Responses in PHP.  The target audience for this article are server programmers or administrators.  Although the code samples shown here are in PHP, similar concepts apply for ASP.net, Perl, Python, Java, etc.; in general, these concepts can be applied to any server-side programming environment that processes HTTP requests and dynamically formulates HTTP responses.

Discussion of HTTP headers

The article covering the HTTP headers used by both clients (such as Firefox 3.5 and beyond) and servers is here, and should be considered prerequisite reading.

Working code samples

The PHP snippets (and the JavaScript invocations to the server) in subsequent sections are taken from the working code samples posted here.  These will work in browsers that implement cross-site XMLHttpRequest such as Firefox 3.5 and above.

Simple cross-site requests

Simple Access Control Requests are initiated when:

  • An HTTP/1.1 GET or a POST is used as request method.  In the case of a POST, the Content-Type of the request body is one of application/x-www-form-urlencodedmultipart/form-data, or text/plain.
  • No custom headers are sent with the HTTP Request (such as X-Modified, etc.)

In this case, responses can be sent back based on some considerations.

  • If the resource in question is meant to be widely accessed (just like any HTTP resource accessed by GET), than sending back the Access-Control-Allow-Origin: * header will be sufficient, unless the resource needs credentials such as Cookies and HTTP Authentication information.
  • If the resource should be kept restricted based on requester domain, OR if the resource needs to be accessed with credentials (or sets credentials), then filtering by the request's ORIGIN header may be necessary, or at least echoing back the requester's ORIGIN (e.g. Access-Control-Allow-Origin: http://arunranga.com).  Additionally, the Access-Control-Allow-Credentials: true header will have to be sent.  This is discussed in asubsequent section.

The section on Simple Access Control Requests shows you the header exchanges between client and server.  Here is a PHP code segment that handles a Simple Request:

  1. <?php
  2. // We'll be granting access to only the arunranga.com domain which we think is safe to access this resource as application/xml
  3. if($_SERVER['HTTP_ORIGIN'] == "http://arunranga.com")
  4. {
  5. header('Access-Control-Allow-Origin: http://arunranga.com');
  6. header('Content-type: application/xml');
  7. readfile('arunerDotNetResource.xml');
  8. }
  9. else
  10. {
  11. header('Content-Type: text/html');
  12. echo "<html>";
  13. echo "<head>";
  14. echo " <title>Another Resource</title>";
  15. echo "</head>";
  16. echo "<body>",
  17. "<p>This resource behaves two-fold:";
  18. echo "<ul>",
  19. "<li>If accessed from <code>http://arunranga.com</code> it returns an XML document</li>";
  20. echo " <li>If accessed from any other origin including from simply typing in the URL into the browser's address bar,";
  21. echo "you get this HTML document</li>",
  22. "</ul>",
  23. "</body>",
  24. "</html>";
  25. }
  26. ?>

The above checks to see if the ORIGIN header sent by the browser (obtained through $_SERVER['HTTP_ORIGIN']) matches 'http://arunranga.com'.  If yes, it returns Access-Control-Allow-Origin: http://arunranga.com .  This example can be seen running here if you have a browser that implements Access Control (such as Firefox 3.5).

Preflighted requests

Preflighted Access Control Requests occur when:

  • A method other than GET or POST is used, or if POST is used with a Content-Type other than one of application/x-www-form-urlencoded,multipart/form-data, or text/plain.  For instance, if the Content-Type of the POST body is application/xml, a request is preflighted.
  • A custom header is (such as X-PINGARUNER) is sent with the request.

The section on Preflighted Access Control Requests shows a header exchange between client and server.  A server resource responding to a preflight requests needs to be able to make the following determinations:

  • Filtration based on ORIGIN, if any at all
  • Response to an OPTIONS request (which is the preflight request), including sending necessary values with Access-Control-Allow-MethodsAccess-Control-Allow-Headers (if any additional headers are needed in order for the application to work), and, if credentials are necessary for this resource,Access-Control-Allow-Credentials
  • Response to the actual request, including handling POST data, etc.

Here is an example in PHP of handling a preflighted request:

  1. <?php
  2. if($_SERVER['REQUEST_METHOD'] == "GET")
  3. {
  4.     header('Content-Type: text/plain');
  5.     echo "This HTTP resource is designed to handle POSTed XML input from arunranga.com and not be retrieved with GET";
  6.    
  7. }
  8. elseif($_SERVER['REQUEST_METHOD'] == "OPTIONS")
  9. {
  10.     // Tell the Client we support invocations from arunranga.com and that this preflight holds good for only 20 days
  11.     if($_SERVER['HTTP_ORIGIN'] == "http://arunranga.com")
  12.     {
  13.     header('Access-Control-Allow-Origin: http://arunranga.com');
  14.     header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
  15.     header('Access-Control-Allow-Headers: X-PINGARUNER');
  16.     header('Access-Control-Max-Age: 1728000');
  17.     header("Content-Length: 0");
  18.     header("Content-Type: text/plain");
  19.     //exit(0);
  20.     }
  21.     else
  22.     {
  23.     header("HTTP/1.1 403 Access Forbidden");
  24.     header("Content-Type: text/plain");
  25.     echo "You cannot repeat this request";
  26.    
  27.     }
  28. }
  29. elseif($_SERVER['REQUEST_METHOD'] == "POST")
  30. {
  31.     /* Handle POST by first getting the XML POST blob, and then doing something to it, and then sending results to the client
  32.     */
  33.     if($_SERVER['HTTP_ORIGIN'] == "http://arunranga.com")
  34.     {
  35.             $postData = file_get_contents('php://input');
  36.             $document = simplexml_load_string($postData);
  37.            
  38. // do something with POST data
  39.             $ping = $_SERVER['HTTP_X_PINGARUNER'];
  40.            
  41.                        
  42.             header('Access-Control-Allow-Origin: http://arunranga.com');
  43.             header('Content-Type: text/plain');
  44.             echo // some string response after processing
  45.     }
  46.     else
  47.         die("POSTing Only Allowed from arunranga.com");
  48. }
  49. else
  50.     die("No Other Methods Allowed");
  51. ?>

Note the appropriate headers being sent back in response to the OPTIONS preflight as well as to the POST data.  One resource thus handles the preflight as well as the actual request. In the response to the OPTIONS request, the server notifies the client that the actual request can indeed be made with the POSTmethod, and header fields such as X-PINGARUNER can be sent with the actual request.  This example can be seen running here if you have a browser that implements Access Control (such as Firefox 3.5).

Credentialed requests

Credentialed Access Control Requests -- that is, requests that are accompanied by Cookies or HTTP Authentication information (and which expect Cookies to be sent with responses) -- can be either Simple or Preflighted, depending on the request methods used.

In a Simple Request scenario, Firefox 3.5 (and above) will send the request with Cookies (e.g. if the withCredentials flag is set on  XMLHttpRequest).  If the server responds with Access-Control-Allow-Credentials: true attached to the credentialed response, then the response is accepted by the client and exposed to web content.  In a Preflighted Request, the server can respond with Access-Control-Allow-Credentials: true to the OPTIONS request.

Here is some PHP that handles credentialed requests:

  1. <?php
  2. if($_SERVER['REQUEST_METHOD'] == "GET")
  3. {
  4. // First See if There Is a Cookie
  5. //$pageAccess = $_COOKIE['pageAccess'];
  6. if (!isset($_COOKIE["pageAccess"])) {
  7. setcookie("pageAccess", 1, time()+2592000);
  8. header('Access-Control-Allow-Origin: http://arunranga.com');
  9. header('Cache-Control: no-cache');
  10. header('Pragma: no-cache');
  11. header('Access-Control-Allow-Credentials: true');
  12. header('Content-Type: text/plain');
  13. echo 'I do not know you or anyone like you so I am going to mark you with a Cookie :-)';
  14. }
  15. else
  16. {
  17. $accesses = $_COOKIE['pageAccess'];
  18. setcookie('pageAccess', ++$accesses, time()+2592000);
  19. header('Access-Control-Allow-Origin: http://arunranga.com');
  20. header('Access-Control-Allow-Credentials: true');
  21. header('Cache-Control: no-cache');
  22. header('Pragma: no-cache');
  23. header('Content-Type: text/plain');
  24. 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!';
  25. }
  26. }
  27. elseif($_SERVER['REQUEST_METHOD'] == "OPTIONS")
  28. {
  29. // Tell the Client this preflight holds good for only 20 days
  30. if($_SERVER['HTTP_ORIGIN'] == "http://arunranga.com")
  31. {
  32. header('Access-Control-Allow-Origin: http://arunranga.com');
  33. header('Access-Control-Allow-Methods: GET, OPTIONS');
  34. header('Access-Control-Allow-Credentials: true');
  35. header('Access-Control-Max-Age: 1728000');
  36. header("Content-Length: 0");
  37. header("Content-Type: text/plain");
  38. //exit(0);
  39. }
  40. else
  41. {
  42. header("HTTP/1.1 403 Access Forbidden");
  43. header("Content-Type: text/plain");
  44. echo "You cannot repeat this request";
  45. }
  46. }
  47. else
  48. die("This HTTP Resource can ONLY be accessed with GET or OPTIONS");
  49. ?>

Note that in the case of credentialed requests, the Access-Control-Allow-Origin: header must not have a wildcard value of "*".   It must mention a valid origin domain.  The example above can be seen running here if you have a browser that implements Access Control (such as Firefox 3.5).

Apache examples

Restrict access to certain URIs

One helpful trick is to use an Apache rewrite, environment variable, and headers to apply Access-Control-Allow-* to certain URIs. This is useful, for example, to constrain cross-origin requests to GET /api(.*).json requests without credentials:

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

See also

https://developer.mozilla.org/en-US/docs/Web/HTTP/Server-Side_Access_Control

Server-Side Access Control的更多相关文章

  1. 转:Oracle R12 多组织访问的控制 - MOAC(Multi-Org Access Control)

    什么是MOAC MOAC(Multi-Org Access Control)为多组织访问控制,是Oracle EBS R12的重要新功能,它可以实现在一个Responsibility下对多个Opera ...

  2. 【MongoDB】The Access control of mongodb

    In this blog we mainly talk about the access control including limitation of ip, setting listen port ...

  3. Oracle ACL(Access Control List)

    在oralce 11g中假如你想获取server的ip或者hostname,执行如下语句 SELECT utl_inaddr.get_host_address FROM dual;  //获取IP S ...

  4. Oracle Applications Multiple Organizations Access Control for Custom Code

    档 ID 420787.1 White Paper Oracle Applications Multiple Organizations Access Control for Custom Code ...

  5. Oracle R12 多组织访问的控制 - MOAC(Multi-Org Access Control)

    什么是MOAC MOAC(Multi-Org Access Control)为多组织访问控制,是Oracle EBS R12的重要新功能,它可以实现在一个Responsibility下对多个Opera ...

  6. Difference between ID and control.ClientID OR why use control.ClientID if I can access control through ID

     https://stackoverflow.com/questions/3743582/difference-between-id-and-control-clientid-or-why-use-c ...

  7. Browser security standards via access control

    A computing system is operable to contain a security module within an operating system. This securit ...

  8. Enhancing network controls in mandatory access control computing environments

    A Mandatory Access Control (MAC) aware firewall includes an extended rule set for MAC attributes, su ...

  9. Access control differentiation in trusted computer system

    A trusted computer system that offers Linux® compatibility and supports contemporary hardware speeds ...

随机推荐

  1. oracle学习----trace文件

    1.查看v$diag_info视图,能查看跟踪文件的位置,具体的名称等信息. name列中,Diag Trace是11g跟踪文件所在位置 Default Trace File是当前会话的跟踪文件名 2 ...

  2. Java类加载及实例化的调用顺序

    标题起得略拗口,大概意思就是说在一个Java类中,域和构造方法的调用顺序. 1. 没有继承的情况 单独一个类的场景下,初始化顺序为依次为 静态数据,继承的基类的构造函数,成员变量,被调用的构造函数. ...

  3. JQuery Jplayer play无效的问题

    最近折腾个H5. 用到Jplayer, 用着不错,至少兼容性强一些. 但是安卓这辆公共汽车型号实在太多.不小心上了一辆奇葩的就容易震到生活不能自理. 我在一台手机上的五六个浏览器上测试,都可以. 把该 ...

  4. TS格式解析

    1.TS格式介绍 TS:全称为MPEG2-TS.TS即"Transport Stream"的缩写.它是分包发送的,每一个包长为188字节(还有192和204个字节的包).包的结构为 ...

  5. Extjs事件继承注意事项

    Extjs事件继承总结: 在基类中只需配置通用事件,无需配置通用界面,通用界面无效,通用事件一直有效 基表格控制器

  6. Google Maps API 调用实例

    本实例介绍如何调用Google Maps API,并实现用鼠标标注地图,保存进数据库,以及二次加载显示等. 1.需要新建一个自定义控件(如:Map.ascx),用于显示Google地图: <%@ ...

  7. iOS iOS与html进行交互

    实现的 效果就是上边那样:首先通过webview 进行网络请求 然后进行显示. 然后点击下一页的按钮 通过js的响应显示另一个网页 最后通过下一页的按钮可以返回到首页. 本文仅仅是h5跟ios 的交互 ...

  8. IOS 学习笔记 2015-04-03 OC-API-文件读写

    // // WPFileHelper.m // OC-API-文件操作 // // Created by wangtouwang on 15/4/3. // Copyright (c) 2015年 w ...

  9. 一段sql的优化

    优化前代码 select * ,ROW_NUMBER() OVER(order by WrongCount desc) as rowId from(select Quba_IDint,Quba_Num ...

  10. docker 中搭建tomcat

    关于docker中tomcat的搭建,没有什么多说的,直接下载官方镜像 docker pull tomcat  (可能会下载到好几个镜像,就是tag不同,有知道为什么的可以告诉我) 然后我看的  ht ...