Firefox 3.5 implements the website of 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 is 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 this initiates requests and processes responses from the SE RVer, as well as a discussion of each header, can is found here (HTTP Access Control). The HTTP Access Control article should is read as a companion article to this one. This article covers processingAccess Control Requestsand formulatingAccess Control ResponsesIn PHP. The target audience for this article is server programmers or administrators. Although the code samples shown here is in PHP, similar concepts apply for ASP, Perl, Python, Java, etc.; In general, these concepts can is applied to any SERVER-SIDE programming environment that processes HTTP requests and Dyna Mically 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 are here, and Shoul D be considered prerequisite reading.
Working code samples
The PHP snippets (and the JavaScript invocations to the server) in subsequent sections is taken from the working Code SAM Ples posted here. These would work in browsers that implement Cross-site XMLHttpRequest
such as Firefox 3.5 and above.
Simple Cross-site Requests
Simple Access Control Requests is initiated when:
- An http/1.1
GET
or a is POST
used as request method. In the-a POST, the content-type of the request body is one of application/x-www-form-urlencoded
, multipart/form-data
, ortext/plain.
- No custom headers is sent with the HTTP Request (such
X-Modified
as, etc.)
In the This case, responses can is sent back based on some considerations.
- If The resource in question are meant to being widely accessed (just like any HTTP resource accessed by GET), than S Ending back the
access-control-allow-origin: *
header'll be sufficient, unless the resource needs credentials such as Cookies and HTTP authentication information.
- If The resource should is kept restricted based on requester domain, OR if the resource nee DS to BES accessed with credentials (or sets credentials), then filtering by the request ' s
ORIGIN
he Ader may is 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'll has to be sent. this is discussed in asubsequent sec tion.
The section on simple Access Control requests shows The header exchanges between client and server. This is a PHP code segment. Handles a simple Request:
<?php//we ' ll be granting access to only the arunranga.com domain which we think are safe to Access this resource as Application/xmlif ($_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 "
The above checks to see if the ORIGIN
header is sent by the browser (obtained through $_server[' Http_origin ']) matches '/HTTP/ Arunranga.com '. If yes, it returns this Access-Control-Allow-Origin: http://arunranga.com .
example can is seen running here if you had a browser that implements Access Control (such a S Firefox 3.5).
preflighted Requestspreflighted Access Control requests occur when:
- A method other than
GET
or was POST
used, or if is POST
used with a other Content-Type
than one application/x-www-form-urlencoded
of, multipart/form-data
, or for instance, if Content-Type
POST
application/xml
The of the body is, a request is preflighted.
- A Custom header is (such as
X-PINGARUNER
) was 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 being able to make the following determinations:
- Filtration based on
ORIGIN
, if any at all
- Response to a
OPTIONS
request (which is the preflight request), including sending necessary values with Access-Control-Allow-Methods
, Access-Control-Allow-Headers
(if an Y additional headers is needed in order for the application to work), and, if credentials is necessary for this resource ,Access-Control-Allow-Credentials
- Response to the actual request, including handling
POST
data, etc.
Example in PHP of handling a preflighted request:
<?php if ($_server[' request_method '] = = "GET") { header (' Content-type:text/plain '); echo "This HTTP resource are designed to handle POSTed XML input from arunranga.com and not being retrieved with GET"; Nbsp; }elseif ($_server[' request_method ') = = "OPTIONS") { //Tell the Client we support Invocations from Arunranga.com and, this preflight holds good for only days if ($_server[' Http_ori GIN '] = = "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" Cannot repeat this request "; }}elseif ($_ server[' request_method ' = = "POST") { /* Handle post by first getting the XML post blob, and then doing S Omething 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-allowed from arunranga.com");} else die ("No other Methods allowed");? >
Note the appropriate headers being sent back on response to the preflight as well as to the OPTIONS
POST
data. One resource thus handles the preflight as well as the actual request. OPTIONS
the response to the request, the server notifies the client, the actual request can indeed is made with the C3/>method, and header fields such as X-PINGARUNER
can is sent with the actual request. This example can is seen running here if you had a browser that implements Access Control (such as Firefox 3.5).
Credentialed requestsCredentialed Access Control requests--that's, requests that's accompanied by Cookies or HTTP authentication Informati On (and which expect Cookie to being sent with responses)--can is either simple or preflighted, depending on the request m Ethods used.
In a simple Request scenario, Firefox 3.5 (and above) would send the Request with a cookie (e.g. if the withCredentials
flag is set on XMLHttpRequest
). If the server responds Access-Control-Allow-Credentials: true
with attached to the credentialed response, then the response was accepted by the client and E Xposed to Web content. In a preflighted request, the server can respond with to the Access-Control-Allow-Credentials: true
OPTIONS
request.
Here are some PHP that handles credentialed requests:
<?phpif ($_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 your or anyone like your I am going to mark your 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 IoT like you! You had been to ', $_server[' server_name '],' At least ', $accesses-1, ' time (s) before! '; }}elseif ($_server[' request_method '] = = "OPTIONS") {//Tell the Client this preflight holds good 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 is only is accessed with GET or OPTIONS");? >
Note that in the case of credentialed requests, the Access-Control-Allow-Origin:
header must not has 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 examplesrestrict access to certain URIsOne helpful trick is to use a Apache rewrite, environment variable, and headers to apply to Access-Control-Allow-*
certain URIs. This was 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=CORSHeader set Access-Control-Allow-Methods "GET" env=CORSHeader 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