瀏覽器跨域請求之credentials

-時間起源-javascript

前段時間,須要弄個簡單的網站出來,訪問遠程的api服務。前端

我是這麼作的。首先是在搭建一個nodejs服務來運行前端頁面。在我請求登陸的時候,能成功返回相應的成功信息。而後,當我再次請求讀取別的接口的時候,返回的信息確實提示我還沒有登陸。此時此刻,我一臉蒙逼。明明我已經登錄了啊。後來偶然得知這是由於瀏覽器的機制問題。java

-初步解決-node

大概的意思是,默認狀況下,標準的跨域請求是不會發送cookie等用戶認證憑據的。因此,當你再次訪問遠程api的時候,cookie是不會被帶上的,因而乎,服務器理所固然地認爲你尚未登陸。MDN上的簡單介紹 credentials 。用XMLHttpRequest請求的時候,咱們須要設置屬性 withCredentials=true ;jquery

 

[javascript] view plain copyajax

 

  1. var xhr = new XMLHttpRequest();  
  2. xhr.open('GET', 'http://www.xxx.com/api');  
  3. xhr.withCredentials = true;  
  4. xhr.onload = onLoadHandler;  
  5. xhr.send();  


這樣一來,cookie相關信息就會被帶上了。json

 

須要注意的是,當這個屬性爲true的時候,遠程服務器也要做相應的處理。在響應頭那裏設置  Access-Control-Allow-Credentials: true 。若是沒有這個設置的話,瀏覽器就會報錯。api

-引入新的問題-跨域

而後,還有一點須要說明的是,當服務器設置了Access-Control-Allow-Credentials: true以後,Access-Control-Allow-Origin就不能設置爲 * 了(別問我爲何知道,我也說不清楚,多是考慮到安全問題吧)。這麼一來,那就陷入一個困境了:遠程服務就是應該設置爲容許瀏覽器跨域訪問的啊,這個屬性不能這麼設置的話,應該怎麼搞呢?因而我查啊查,搜啊搜,終於把這個問題完美解決了。瀏覽器

-再度解決-

Access-Control-Allow-Origin的做用在於,容許特定白名單用戶(瀏覽器)訪問我這個接口。當設置爲 * 的時候,表示全部用戶都能訪問。若是值爲 'http://xxx.com',則表示只接受來自這個域名的請求,其餘的一概拒絕。而咱們想要的效果就是想設置爲 * 。自從用了Access-Control-Allow-Credentials: true,就不能設置Access-Control-Allow-Origin:'*'了。全部,咱們能夠換一種思路,當a用戶進來的時候,咱們設置a用戶爲白名單就好,同理b用戶也是。也就是說,誰訪問,我就設置誰爲白名單。當瀏覽器進行跨域請求的時候,服務器能獲取其相應的請求頭,其中一個是 Origin 屬性,表示請求的域。咱們只要設置這域爲白名單就好。每種服務器語言的設置方法可能都不同,但原理是同樣的。 大概以下

 

[javascript] view plain copy

 

  1. responce.set('Access-Control-Allow-Origin', request.get('origin'));  

好。ok了。能夠洗洗睡了。

 

--------------------------------------------------------------

 

note: 上面的是使用原生的ajax請求,實際上不少人都選擇諸如jquery這類框架。我以前是在beforeSend方法那裏設置 xhr.withCredentials=true。而後悲劇地發現根本不能達到個人預期效果。其實,不是這麼用的。應該是做爲一個屬性,而不是方法裏面設置。與data屬性並列設置就好。因此看起來是這樣子的

 

[javascript] view plain copy

 

  1. function func() {  
  2.         $.ajax({  
  3.             type: "GET",  
  4.             dataType: "json",  
  5.             xhrFields: {  
  6.                 withCredentials: true    // 要在這裏設置  
  7.             },  
  8.             url: 'https://xxx.com/api/login',  
  9.             success: function (data) {  
  10.   
  11.             },  
  12.             beforeSend: function (xhr) {  
  13. //                下面的設置無效  
  14. //                xhr.withCredentials = true;  
  15.             },  
  16.             error: function (err) {  
  17.                 alert(JSON.stringify(err))  
  18.             }  
  19.         })  
  20.     }  

好了,故事完了。打字好累,真的要洗洗睡了。

相關文章
相關標籤/搜索