Cross Origin Resource Sharing

當你想要跨網域 ajax request,以往只有 jsonp(script) or iframe,現在我們有 CORS..


簡介
原理大略是新瀏覽器與伺服器都支援了這個新的協定,當要跨網域 ajax 時瀏覽器會自動加上 Access-Control-Request 的 headers 並包含 Origin 的 header 來詢問該伺服器是否允許此網域(origin)發出跨網域的請求。

如果該伺服器回應了 Access-Control-Allow,就能真的繼續往下處理,否則就會
XMLHttpRequest cannot load http://cross.mlwmlw.org/. No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://mlwmlw.org’ is therefore not allowed access.

如果是 POST 因為會有資料與狀態改變的問題,所以會先發出一個假請求 http Options,如果有 allow 才會真的再發一次 http post。

PHP headers

header('access-control-allow-origin: http://other.mlwmlw.org');
header('access-control-allow-credentials: true');
header('access-control-allow-headers: Origin, X-Requested-With, Content-Type, Accept');

IE8
新瀏覽器都支援,除了復古的 IE,要透過 activeX ,如同 ajax 跟 event 都獨樹一格一樣,cross domain 他也要另外用 ie only 的 XDomianRequest(xdr) 這個與規格不一致的物件。

IE8 的 xhr 不支援 CORS 但有一個 ie only 的物件能有限的達成此功能,好加在 jQuery ajax 有擴充介面,能透過 Plugin 來擴充 ajax 函式來繼續透過相同 ajax 的 api 來發出請求。
jQuery Plugin https://github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest

Cookie
預設不允許 request 處理 cookie,阿。。那怎麼辦?打開就好拉。
with Cookie (withCredentials)
開啟此參數以後才得以允許 set Cookie ,需要配合伺服器跟 client。

header('access-control-allow-credentials: true');
//jQuery
$.ajax({..
xhrFields: {
       withCredentials: true
})
//angularjs
$http.post(url, {withCredentials: true})

安全性議題
會動了,但..被 XSS 攻擊造成的危險擴大了。

延伸閱讀
enable CORS
http://enable-cors.org/server.html
W3C specification
http://www.w3.org/TR/cors/
Wiki
http://en.wikipedia.org/wiki/Cross-origin_resource_sharing

Mozilla
https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS
https://developer.mozilla.org/zh-TW/docs/HTTP/Access_control_CORS

IE8 XDomainRequest
http://quickleft.com/blog/cookies-with-my-cors
http://msdn.microsoft.com/en-us/library/dd573303(v=vs.85).aspx

codeIgniter ReseServer Support Patch
https://github.com/philsturgeon/codeigniter-restserver/commit/81cff3270ca3b4fa09034a09e73129f28e49c513

html5rocks CORS
http://www.html5rocks.com/en/tutorials/cors/

 

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *