2010-03-03 101 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