Server-Side Access Control
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 aPOST
is used as request method. In the case of a POST, the Content-Type of the request body is one ofapplication/x-www-form-urlencoded
,multipart/form-data
, ortext/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'sORIGIN
(e.g.Access-Control-Allow-Origin: http://arunranga.com
). Additionally, theAccess-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:
<?php
// We'll be granting access to only the arunranga.com domain which we think is safe to access this resource as 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>";
}
?>
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
orPOST
is used, or ifPOST
is used with aContent-Type
other than one ofapplication/x-www-form-urlencoded
,multipart/form-data
, ortext/plain.
For instance, if theContent-Type
of thePOST
body isapplication/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 withAccess-Control-Allow-Methods
,Access-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:
<?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")
{
// Tell the Client we support invocations from arunranga.com and that 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: 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")
{
/* Handle POST by first getting the XML POST blob, and then doing something to it, and then sending results to the client
*/
if($_SERVER['HTTP_ORIGIN'] == "http://arunranga.com")
{
$postData = file_get_contents('php://input');
$document = simplexml_load_string($postData);
// do something with POST data
$ping = $_SERVER['HTTP_X_PINGARUNER'];
header('Access-Control-Allow-Origin: http://arunranga.com');
header('Content-Type: text/plain');
echo // some string response after processing
}
else
die("POSTing Only Allowed from arunranga.com");
}
else
die("No Other Methods Allowed");
?>
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 POST
method, 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:
<?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");
?>
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:
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
See also
- Examples of Access Control in Action
- HTTP Access Control covering the HTTP Headers
- XMLHttpRequest
- Web Fonts
https://developer.mozilla.org/en-US/docs/Web/HTTP/Server-Side_Access_Control
Server-Side Access Control的更多相关文章
- 转:Oracle R12 多组织访问的控制 - MOAC(Multi-Org Access Control)
什么是MOAC MOAC(Multi-Org Access Control)为多组织访问控制,是Oracle EBS R12的重要新功能,它可以实现在一个Responsibility下对多个Opera ...
- 【MongoDB】The Access control of mongodb
In this blog we mainly talk about the access control including limitation of ip, setting listen port ...
- Oracle ACL(Access Control List)
在oralce 11g中假如你想获取server的ip或者hostname,执行如下语句 SELECT utl_inaddr.get_host_address FROM dual; //获取IP S ...
- Oracle Applications Multiple Organizations Access Control for Custom Code
档 ID 420787.1 White Paper Oracle Applications Multiple Organizations Access Control for Custom Code ...
- Oracle R12 多组织访问的控制 - MOAC(Multi-Org Access Control)
什么是MOAC MOAC(Multi-Org Access Control)为多组织访问控制,是Oracle EBS R12的重要新功能,它可以实现在一个Responsibility下对多个Opera ...
- 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 ...
- Browser security standards via access control
A computing system is operable to contain a security module within an operating system. This securit ...
- 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 ...
- Access control differentiation in trusted computer system
A trusted computer system that offers Linux® compatibility and supports contemporary hardware speeds ...
随机推荐
- 给TextView添加超链接的四种方式
因为在上上篇博客中介绍了SpannableString的使用(SpannableString使用详解),由此想到给TextView添加超链接究竟有多少种方式?经过个人总结,现在一共发现四种,如果还有其 ...
- 调用iframe 中的js[兼容各种浏览器]
*chrome浏览器需要在服务器环境中测试 <!DOCTYPE html> <html> <head> <meta http-equiv="cont ...
- cobbler部署
1.cobbler介绍 Cobbler是一个快速网络安装linux的服务,而且在经过调整也可以支持网络安装windows.该工具使用python开发,小巧轻便(才15k行python代码),使用简单的 ...
- 7.Composer的安装和使用
1.安装Composer: 局部安装 要真正获取 Composer,我们需要做两件事.首先安装 Composer (同样的,这意味着它将下载到你的项目中): curl -sS https://getc ...
- 关于dialog的一点知识
一般我们比较常用的就是AlertDialog,这个一般也不直接构造,而是用系统提供的builder构造器去构造一个dialog. AlertDialog.Builder builder = new A ...
- ASC码 .
有些时候需要用到一些字符的ASC码,到网上查找太麻烦,现在记录下来. 第128-255号为扩展字符(不常用) Dec Hx Oct Char Dec Hx Oct Char Dec Hx Oct ...
- 手把手教你写电商爬虫-第四课 淘宝网商品爬虫自动JS渲染
版权声明:本文为博主原创文章,未经博主允许不得转载. 系列教程: 手把手教你写电商爬虫-第一课 找个软柿子捏捏 手把手教你写电商爬虫-第二课 实战尚妆网分页商品采集爬虫 手把手教你写电商爬虫-第三课 ...
- 输出图像到文件 imwrite()[OpenCV 笔记7]
bool imwrite(const string& filename, InputArray img, const vector<int>& params=vector& ...
- (hdu)5391 Zball in Tina Town
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5391 Problem Description Tina Town is a friendl ...
- [CLR VIA C#] chapter2 building,packaging,deploying, and administering
今天整理一下 assembly, 总感觉第一章 到 第三章 没怎么仔细看, 导致后面作者说前面说过的, 我就心里不舒服, 前面3章很干很涩, 好好啃啃, 先作一些简单笔记, 最后再来 整体整理, 反正 ...