關鍵點在於不論是 XMLHttpRequest 或者是用 ajax,只要有夾帶 authroization (user name & password) 要做認證的話,會多一個 OPTIONS request,而且 javascript 這邊也要做修改。
注意: 這是很不安全的CORS,有可能被釣魚,所以盡可能不要使用
一般狀況下透過 XMLHttpRequest 或 ajax 去呼叫其他 server 上的 api 或網頁,只要對方 server 的 cors 設定有做好就沒問題,但是如果要加上 authorization 資訊,javascript 這邊要指定這個 request 必須是 with credentials,且要把 authorization 資料放在 header 中。
<!DOCTYPE html> <html> <head> <meta HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script> </head> <body> <div class="container" style="padding-top:40px;"> <span id="i01">test</span> <span id="i02">test2</span> </div> </body> <script> // jquery $('#i01').click(function(){ $.ajax({ type: "GET", url: "http://API.SERVER.URL/PATH/TO/API", dataType: 'json', async: false, beforeSend: function(request){ request.withCredentials = true; request.setRequestHeader("Authorization" , "Basic AUTHORIZATION_DATA=="); // AUTHORIZATION_DATA = btoa("USERNAME:PASSWORD"); }, success: function (){ alert('Success!'); } }); }); // javascript $('#i02').click(function(){ var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { alert('Success!'); } }; var url = 'ttp://API.SERVER.URL/PATH/TO/API'; xhttp.open("GET", url, true); xhttp.setRequestHeader('Authorization','Basic AUTHORIZATION_DATA=='); // AUTHORIZATION_DATA = btoa("USERNAME:PASSWORD"); xhttp.send(); }); </script> </html>
而在被呼叫的 api 部分(以 php phalcon framework 為例子),則不僅要把 X-Requested-With 加入 allow headers 裏頭,連 Authorization 也要。
public function apiAction() { $resp = new PhalconHttpResponse(); $resp->setHeader("Access-Control-Allow-Origin", "*"); $resp->setHeader('Access-Control-Allow-Headers', 'X-Requested-With, Authorization'); $resp->sendHeaders(); $this->view->disable(); //$headers = apache_request_headers(); //var_dump($headers['Authorization']); $resp->setHeader("Content-Type", "application/json"); $resp->setStatusCode(200, "OK"); $resp->setContent('{"message": "Not a valid verifiy"}'); $resp->send(); return; }
最後就可以看到這樣的結果。