2010-03-03 147 views
6

以下問題同時發生在Safari和Chrome上,因此可能是WebKit問題。Safari和Chrome後退按鈕更改隱藏並提交表單

頁答:需要您登錄到看到一個頁面,包含有一個類型=提交按鈕,用名字=提交和價值構成=一

頁B:其他頁面

頁面C:請求用戶登錄頁面,包含一個類型=提交按鈕的表單,其中name = submit和value = c

用戶訪問頁面A,然後是頁面B.然後空閒和用戶的登錄會話超時。用戶點擊返回按鈕返回到頁面A.瀏覽器將用戶重定向到頁面C.

在Safari和Chrome上,呈現C時,頁面C上的表單具有類型= submit按鈕,名稱= submit,但值顯示爲「a」。

如果您在頁面C上重新加載,則「c」顯示爲name = submit按鈕的值。

類型=隱藏輸入字段出現同樣的問題;當用戶點擊返回按鈕時,它們的值也會從其他表單中更改爲其他值。此外,這個問題也顯示了沒有重定向,只需提交回來。在這種情況下,前一頁呈現的隱藏和提交CGI變量的值不正確。

到目前爲止唯一能解決的問題是在頁面C加載後,使用Javascript重置type = hidden和type = submit變量值,以確保值是正確的。但這並不乾淨,普遍適用。

缺少修復此錯誤的WebKit,有沒有人遇到更好的解決方法?

謝謝。

回答

17

經過大量的挖掘,我找到了答案。那麼,不是一個答案,但爲什麼會發生這種情況。我希望這能節省一些時間。

當前基於WebKit的瀏覽器(截至2010年3月16日),例如, Safari和Chrome展示以下錯誤。也許有人可以看看。謝謝。問題1:如果頁面A有多個表單元素F1和F2,並且第一個(按HTML形式出現)窗體F1的自動完成設置爲「關閉」(即),但是F2具有自動完成設置到「開」(默認行爲),然後導航離開頁面A,然後點擊瀏覽器後退按鈕返回頁面A,F1和F2可能會自動完成不正確。特別是,如果F1和F2都有具有相同名稱和類型的輸入元素,比如N和T(即),那麼當使用後退按鈕導航回頁面A時,F1.N的值將自動與F2.N的值完成。問題2:首先,瀏覽器點擊頁面A,服務器返回一個帶有表單元素F1和F2的HTML頁面(這兩個表單都設置了自動完成功能)。然後,用戶導航離開頁面A,然後使用瀏覽器後退按鈕返回到頁面A.在第二次訪問頁面A時,WebKit向服務器發出另一個A請求(這與FireFox的行爲不同,後退按鈕不向服務器發出添加請求)。如果服務器返回不同的HTML頁面(例如,因爲用戶會話已註銷),表單元素F3和F4與F1和F2不同,但是由具有相同名稱和類型的輸入元素組成,則F3和F4將自動填充F1和F2輸入元素值,甚至爲輸入元素類型隱藏並提交。

解決

錯誤1:除非你有這個設置爲相同的HTML網頁上的所有形式永遠不會使用自動完成=「關閉」。

錯誤2:特定的情況下,沒有很好的通用解決方案。我們找到了一個可以接受的解決方法,通過包含隱藏表單來確保頁面A的兩個版本具有相似的表單;第一個版本有F1,F2,F3,第二個版本有F1,F2'和F3,其中F2'是F2的隱藏版本。如果我們不包含F2',那麼頁面A的第二個版本是F1,即使對於F3中的隱藏和提交元素,F3和F3也將自動填充F2的元素值。 WebKit的CODE

分析這兩個錯誤發生在代碼的同一部分,但也許可以被視爲兩個獨立的錯誤。代碼位於WebKit代碼樹的WebCore子目錄中。

錯誤1:在Document :: formElementsState中,具有自動完成開啓(通過HTMLInputElement :: saveFormControlState檢查)的輸入元素,將其狀態保存在向量中。但是,在HTMLFormControlElementWithState :: finishParsingChildren中,無論自動完成是ON還是OFF,每個表單元素都會從上述向量中恢復狀態。這導致錯誤1.

Bug的修復1:這應該是一個相當直接的修復 - finishParsingChildren不能恢復狀態,如果元素具有自動完成關閉。

免責聲明:我沒有在Mac上發展。我只用它,我們開發一個網站。我今天瀏覽WebKit代碼。因此,我沒有創建或測試一個補丁。

的Bug 2.這要複雜得多。

我認爲在一個設計決策無關的自動完成功能,WebKit是旨在重新抓取頁面A如果用戶正在使用後退按鈕回到歷史頁面A.

(我有興趣在聽到這個也是如此)

基本上,WebKit做出了不正確的假設,即頁面A的第二次獲取導致與第一次獲取相同的HTML或至少相同的一組表單。如果情況並非如此,那麼自動完成邏輯不再產生正確/預期的行爲。

當WebKit爲頁面保存狀態時,它調用Document :: formElementsState,它只是創建一個對映射圖,並將每個輸入元素的名稱,類型和值對放入映射中。如果兩個單獨格式中的兩個輸入元素具有相同的名稱和類型,則這兩個值都將被保存。

舉例來說,假設頁A具有形式F1和F2,F1和具有名稱a1和a2輸入元件,與類型T1和T2時,分別用值v1和v2。 F2具有名稱爲a3和a2的輸入元素,分別具有類型t1和t2以及值v3和v4。WebKit將此頁的狀態保存爲(在JSON中)

{「a1,t1」:[v1],「a2,t2」:[v2,v4],「a3,t1」:[v3]}

如果用戶使用瀏覽器後退按鈕重新訪問頁面A,WebKit將嘗試使用上述狀態從服務器獲取的新版本頁面A上自動完成表單。如果新版本的頁面A與最後一個版本具有完全相同的形式,那麼一切正常。如果不是,那麼WebKit會產生不正確的行爲。例如,假設第二次訪問頁面A,服務器返回一個表單F3,並且F3具有名稱爲a4和a2的輸入元素,類型爲t1和t2,則F3的a2元素將填充爲v2,從之前保存頁。

(注:存儲狀態和恢復狀態,如在代碼中使用的實際的邏輯,略有不同,但概念是相同的)

此問題表現在網站上時用戶會話可能過期,和會話過期後,點擊頁面A可能會產生稍微不同的HTML。例如。可能會給你一個「請登錄」表格,或者可能會給你大致相同的內容,但是頂部的搜索用戶數據表格會出現一個登錄表單。在這些情況下,可見的文本輸入元素,隱藏的輸入元素和提交輸入元素可能都會通過WebKit更改其值。

問題2修復:這很困難,因爲當用戶使用後退按鈕時,WebKit會重新提取頁面A.如果新版本的頁面A與舊版本不同,WebKit無法輕鬆地將表單的狀態從舊版本的頁面與某種形式(如果它存在)在新版本上進行匹配。實際上,您無法要求所有表單都具有相同的DOM標識,即使您這樣做了,仍然不完全正確,因爲DOM標識必須在HTML頁面內是唯一的,但不需要在單獨的HTML文檔中是唯一的。

我能想到的唯一修復方法是:當您從第一次訪問頁面A保存狀態時,採用頁面的MD5或SHA1哈希,並將其保存爲輸入元素狀態。當您回到頁面A時,如果MD5或SHA1哈希值相同,則只能恢復狀態。

4

我不確定,但嘗試將autocomplete ='off'添加到所有表單。

<form .... autocomplete = 'off'> 
+0

很好的嘗試,但沒有奏效。 如果您仔細考慮,自動填充功能的確適用於瀏覽器功能,它可以完成您以前的答案。我看到的錯誤是Webkit嘗試在用戶點擊「返回」按鈕時在上一頁「保留」用戶輸入數據的結果。 – OverClocked 2010-03-04 04:19:47

+0

@ a1ex07:對不起,你的建議幾乎是正確的。您必須關閉自動填充功能,而我之前對有關自動填充的評論與自動填寫相似的說法不正確。不是。但訣竅是您必須關閉所有字段中的自動填充功能。看到我對自己的問題的「答案」。 – OverClocked 2010-03-16 21:09:52

+0

我在清除某些隱藏輸入的值時遇到了問題,並向表單添加了autocomplete ='off'來解決此問題。謝謝! – 2014-10-20 12:45:47

1

autocomplete="off"

對我不起作用。我發現了另一個解決辦法,可以使用text領域,使用

DIV style="display:none"

隱藏這些領域,並在DIV標籤添加input_type="text" value="s"領域

+0

'display:none'在谷歌瀏覽器中爲我工作。形式A的價值,例如'order_type =「new」'被錯誤地放到了表單B中。即使實際的html(查看源)說'order_type =「up」「,提交升級表B的人也會有'order_type ='new''。 現在我正在從Mobile Safari(Mozilla/5.0(iPad; CPU OS 7_0_4,如Mac OS X)AppleWebKit/537.51.1(KHTML,如Gecko)版本/ 7.0 Mobile/11B554a Safari/9537)獲得怪物結果。53) 在這種情況下,它應該有'order_id =「new」'或'order_id =「1」'。當它們返回時,它會自動填充它們的*名稱*到order_id字段中! – 2013-12-04 04:25:40