2013-12-11 41 views
3

多個Web應用程序的身份驗證協議(如WS-聯邦和SAML協議,即所謂的「被動」的協議,顯然還ASP.NET窗體身份驗證,看this StackOverflow question和AppEngine上,看到this GWT bug comment)失去了原有的「網址片段「,即#號後面的部分。作爲SAML令牌認證的一部分丟失了URL片段;解決方法/標準模式?

會發生什麼情況大致如下:在一個乾淨的瀏覽器(所以沒有緩存的信息/餅乾/登錄信息),我打開URL(1)http://example.com/myapp/somepage?some=parameter#somewhere。這使得瀏覽器請求(2)http://example.com/myapp/somepage?some=parameter,服務器將我重定向到我的身份提供者(包括身份驗證請求中的URL(2)),並最終將我重定向回我來自的URL(2):這是服務器知道的唯一URL。但我想去URL(1),並且URL片段('錨')已經丟失,實際上已經在第一步。

這似乎是這些協議的基本限制,因爲服務器根本看不到URL片段。我知道它根據瀏覽器從服務器請求(2)的規範,當我導航到(1)時,導致對SAML協議,WS聯合會等這種片段丟失的限制。我的問題是:我如何解決這個限制?

顯而易見的解決方法是避免網址片段,如在this answer建議。但是,對於我們特定的Web應用程序來說,這並不好,因爲我們在單頁面GWT應用程序中使用了可加入書籤的URL片段,以確保應用程序內的導航不會導致頁面重新加載。

我的問題:在這種情況下還有其他的解決方法或標準模式嗎?

(我在GWT + SAML協議解決方案特別感興趣。)

回答

0

根據RFC 1738錨標記請求資源時不被客戶端發送到服務器。

錨標籤用於標識資源中的位置,而不是服務器上的不同資源。爲了識別資源中的位置,客戶端需要從服務器獲取完整的資源,並且該過程不需要傳送關於片段的信息(因爲它對服務器沒有任何意義)。

如果您希望將片段字符(#)發送到服務器,那麼您需要將它編碼到查詢字符串中,或​​者客戶端(瀏覽器)在發送URL時會簡單地忽略該部分請求到服務器。

編輯:

我不知道任何真正的解決辦法,但要解決這個問題,你需要保存完整的返回URL(錨標記)在客戶端上的某個地方,因爲服務器不知道關於錨的任何事情。爲此,您可以使用SessionStorage(http://www.w3schools.com/html/html5_webstorage.asp)臨時存儲ReturnUrl,直到登錄過程完成。請注意,舊版瀏覽器不支持(如< = IE7)。

在這種情況下,解決辦法將是這個樣子:

<script> 
    if(typeof(sessionStorage) == 'undefined') 
    { 
     sessionStorage = { 
      getItem: function(){}, 
      setItem: function(){} 
     }; 
    } 

    window.onload = function() 
    { 
     var key = 'ReturnUrl'; 

     //try to get last returnUrl with anchors 
     var returnUrl = sessionStorage.getItem(key); 

     //if we got something, do the navigation 
     if(returnUrl !== undefined && returnUrl !== document.URL) 
     { 
      //clean it up 
      sessionStorage.setItem(key, null); 
      //navigate to last URL 
      window.location = returnUrl; 
     } 
     else 
     { 
      //store url 
      sessionStorage.setItem(key, document.URL); 
     } 
    } 
</script> 

PS。唉,如果有一些語法錯誤,因爲我從頭頂寫下來,沒有嘗試它。

+0

我知道了,我已經澄清了相應的問題。我正在尋找解決方法。 –

+0

我編輯了我的答案並添加了解決方法... –

1

你基本上有兩種選擇:

  • 忌用location.hash(使用HTML5的pushState代替,至少在支持它的瀏覽器;和/或建議的方式來產生永久鏈接你的應用程序中 - 谷歌團體是這樣)

  • 使用JavaScript做重定向。即而不是從服務器發送重定向,發送一個空的HTML頁面,其中包含一些腳本,其中包含完整的URL(散列表),並使用location.assign()location.replace()進行重定向。有一點運氣(取決於服務器),您將在驗證後重定向到完整的URL。

當然,你可以一舉兩得:如果該鏈接是一個深層鏈接到應用程序,然後執行重定向(即假定沒有哈希),否則發送頁面JS以確保您不要丟失任何狀態目前在散列

終於顯而易見的第三個解決方案遠非理想:不要做任何事情,並嘗試教育用戶,當他們需要(重新)認證時,他們應該重新粘貼網址或重新點擊鏈接或重新點擊書籤。