With the emergence of the Cross Origin Resource Sharing (CORS) specification, now a candidate for W3C Recommendation, web application developers have a browser-supported mechanism to make XmlHttpRequests to another domain in a secure manner.
As of this writing, we can finally say that CORS is supported by all major browsers. It initially appeared in Firefox 3.5, Safari 4, and Chrome 3. Internet Explorer 10 now has native support.
What is a Cross-Origin Request?
If the script on your page is running from domain mydomain.com and would like to request a resource via an XmlHttpRequest or XDomainRequst from domain otherdomain.com, this is a cross-origin request. Historically, for security reasons these types of requests have been prohibited by browsers.How Does it Work?
The CORS mechanism works by adding HTTP headers to cross-domain HTTP requests and responses. These headers indicate the origin of the request and the server must indicate via headers in the response whether it will serve resources to this origin. This exchange of headers is what makes CORS a secure mechanism. The server must support CORS and indicate that the domain of the client making the request is permitted to do so. The beauty of this mechanism is that it is automatically handled by the browser and web application developers do not need to concern themselves with its details.Simple Requests
For simple cross-site requests (i.e., GETs and POSTs that don’t set custom headers and the request body is plain text or form data), the browser simply includes additional Origin and Referrer headers indicating the requesting domain. For example to retrieve the resource called some-resource at otherdomain.com using the jQuery Ajax API, a developer would simply write [using CoffeeScript for code examples]:
1
2
3
4
5
|
1
2
3
| GET http://otherdomain.com/some-resource/ HTTP/1.1 Referer: http://mydomain.com/myapp/ Origin: http://mydomain.com |
1
2
| Access-Control-Allow-Origin: http://mydomain.com Content-Type: application/json |
Preflighted Requests
The CORS specification requires browsers to preflight requests that:- Use request methods other than GET, POST, or HEAD
- Have custom headers
- Have request bodies with Content-Type other than text/plain, application/x-www-form-urlencoded, or multipart/form-data
1
2
3
4
5
6
7
8
9
10
11
12
13
| $.ajax( type: 'PUT' headers: 'X-Foo': 'bar' data: someResource ).done successFn |
1
2
3
4
5
6
| OPTIONS http://otherdomain.com/some-resource/ HTTP/1.1 Origin: http://mydomain.com Access-Control-Request-Method: PUT Access-Control-Request-Headers: X-Foo |
1
2
3
4
5
| HTTP/1.1 200 OK Access-Control-Allow-Origin: http://mydomain.com Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS Access-Control-Allow-Headers: X-Foo Access-Control-Max-Age: 3600 |
1
2
3
| PUT http://otherdomain.com/some-resource/ HTTP/1.1 Content-Type: application/xml; charset=UTF-8 X-Foo: bar |
Credentialed Requests
A browser will not send Cookies or HTTP Auth information in a cross-domain XmlHttpRequst. The client application must indicate that they should be sent by setting the withCredentials property of the XmlHttpRequest or XDomainRequest. By default, this value is false and not set. From the simple request example above, if we wanted to include any cookies that the user may have acquired for domain otherdomain.com along with the request to retrieve the resource called some-resource at otherdomain.com the client would setup its Ajax request as follows:
1
2
3
4
5
6
7
8
9
| $.get( xhrFields: 'withCredentials': true ).done successFn |
The Obligatory Note on Internet Explorer
Internet Explorer 8 and 9 have limited support for CORS. Namely:- Only GET and POST with a content type of plain/text are supported
- It does not support preflight
- No custom headers may be added to the request
- Credentialed requests are not supported
- Requests must be targeted to the same scheme as the hosting page
Testing
A great resource for testing CORS requests can be found at test.cors.org. This test site allows you to:- Send CORS requests to a remote server to verify its capabilities
- Send CORS requests to a test server to explore CORS features
Alternatives to CORS
If your web application must run in browsers that do not support CORS or interact with servers that are not CORS-enabled, there are several alternatives to CORS that have been utilized to solve the cross-origin communication restriction.- JSONP. This is a technique that exploits the HTML script element exception to the same-origin security policy. Script tags can load JavaScript from a different domain and query parameters can be added to the script URI to pass information to the server hosting the script about the resources that you wish to access. The JSONP server will return JavaScript that is evaluated in the browser that calls an agreed upon JavaScript function already on the page to pass server resource data into your page.
- OpenAjax Hub. This is an JavaScript Ajax library that allows integration of multiple client-side components within a single web application. Trusted and untrusted components to co-exist within the same page and communicate with each other as long as they all include the OpenAjax Hub JavaScript library. The framework provides a security manager to allow the application to set security policies on component messaging. Iframes are used to isolate components into secure sandboxes.
- easyXDM. This is a JavaScript library that allows for string-based cross domain communication via iframes. It works on the same principals as OpenAjax Hub but does not have the security manager component.
- Proxied Iframe. This do-it-yourself technique involves including an iframe on your page from the domain you wish to communicate with. This assumes that you are able to host pages on this other domain. The JavaScript running in the iframe serves as a rest proxy to the server containing the resources you wish to access. Communication between your application and the rest proxy will take place using post message. Post message is part of the HTML5 standard, but there is also a jQuery implementation for non HTML5-compliant browsers.
No comments:
Post a Comment