10

我已經構建了Spring MVC的REST API後端,並使用Spring Security基本身份驗證進行了安全保護。JQuery跨域基本認證調用

我想從JavaScript客戶端跨域Ajax調用REST API。我不想使用JSONP,因爲我不想限制GET調用。我使用CORS,並將正確的標題放在服務器端。

假設我的REST API位於域localhost:8087上,並且我的客戶端位於localhost:8086上,這是跨域調用。

在我的JavaScript客戶端,我做的AJAX調用使用jQuery:

<script> 
     $.ajax ({ 
      url: "http://localhost:8087/SpringMVC/users/user1", 
      beforeSend: function (xhr) { xhr.setRequestHeader ("Authorization", "Basic xxxxxxxxxxxx"); }, 
      success: function(val) { console.log(val); alert("success" + val); }, 
      error: function(val) { console.log(val); alert("error" + val); } 
     }); 
</script> 

我的問題是,jQuery的不發送HTTP請求的授權頭,我不知道爲什麼。我不明白,因爲我在beforeSend方法中這樣做,所以它應該在HTTP請求中。結果:我有一個401錯誤。

當我嘗試從相同的域本地主機:8087,這是不是跨域的腳本了,我沒有問題。

這怎麼可能?

我的腳本只是一個測試。我不打算把我的用戶名/密碼放在客戶端。但是我想測試如何對基本的auth保護的REST API執行ajax調用。我想我必須在服務器端發送安全的用戶名/密碼,REST API會將我發回給我一個cookie,並且我不需要再通過用戶名/密碼來接收我對REST API的下一個ajax調用。我對嗎 ?

我已經使用Chrome高級REST客戶端測試了我的REST API,它的工作方式與此類似。對於我需要傳遞授權標頭的第一個請求。然後它不是必需的。它應該像我的JavaScript網絡客戶端那樣工作嗎?我打算使用Node.JS和Backbone來構建它。

非常感謝。

EDIT2:似乎真的是一個CORS瀏覽器問題。我在服務器端爲OPTIONS方法添加了頭部訪問控制 - 允許 - 方法,它可以在Chrome上運行。我有權訪問JSON響應,而不再有錯誤。但我仍然需要爲下一個請求使用授權標頭。如何告訴jQuery使用發送的cookie?

當我與Firefox 11嘗試,我必須JSON響應進不去,我有錯誤:

"NetworkError: 401 Non-Autorisé - http://localhost:8087/SpringMVC/users/user1" 
+0

你是base64編碼你的用戶名/密碼? – 2012-04-08 14:59:21

+0

是的,我把它xxxxxxxx而不是真正的用戶名:密碼。 – rico 2012-04-08 15:15:25

回答

8

顯然,Chrome和Firefox治療跨域請求有點不同。 在進行跨域請求之前,他們使用HTTP OPTIONS方法執行所謂的「預檢」請求。 Chrome和Firefox之間的區別在於,Chrome也會將Authorization標頭與憑據一起發送,而Firefox則不會。

然後,它仍然是Spring Security的配置問題。我的url/users/*對所有HTTP方法都是安全的,包括OPTIONS。就Firefox而言,由於授權標題未發送,我的請求未被授權。如果我將安全的url/users/*限制爲GET方法,那麼它完全適用於Firefox。所以我不得不只加在我的春季安全配置:

<intercept-url pattern="https://stackoverflow.com/users/*" access="isAuthenticated()" method="GET"/> 

之後,我有選擇,我可以添加其他方法固定在攔截的URL,除了選項,或者我可以限制HTTP方法在我的Spring MVC控制器中調用GET,它甚至可以根據Javadoc處理我的OPTIONS調用。我選擇了第二種解決方案。但是,如果有人找到解決方案來強制Firefox發送像Chrome那樣的憑據,那將會很棒,我會選擇這個。

2

波多黎各呈現將是春季安全配置方案的另一種選擇:

<http ... use-expressions="true"> 
    <intercept-url pattern="https://stackoverflow.com/users/*" access="permitAll" method="OPTIONS"/> 
    <intercept-url pattern="https://stackoverflow.com/users/*" access="isAuthenticated()"/> 
    ... 
</http> 

HTTP OPTIONS請求都將通過認證和任何其他HTTP方法不會。

請注意use-expressions XML屬性設置爲true in <http> element。那麼Spring Security將期望<intercept-url>元素的access屬性包含春EL表達式,像permitAllisAuthenticated()