我有一个包含两个密码字段的典型注册表单。
<form>
<%= Html.TextBox("Email", null) %>
<%= Html.Password("password", null) %>
<%= Html.Password("confirmPassword", null) %>
<input type='submit' />
</form>
如果表单验证失败并重新显示,则文本字段会保留其值,但密码字段始终为空。
为什么密码字段不能保留其值?更重要的是,我有什么理由不应该覆盖这种行为吗?
我觉得这种行为会降低可用性,并且更喜欢密码字段的行为方式与文本框字段相同 - 保留验证错误时输入的值。
我正在使用ASP.NET MVC,但这个问题更多地涉及可用性和安全性。我理解我所看到的是预期的行为,并且查看Password(...)
方法会向我显示它明确忽略了ModelState
中的值。
答案 0 :(得分:16)
您可以在常规输入类型=密码字段上发回该值。
但是,如果您使用的是.net输入控件,那么它会在将html发送回客户端之前清除值的内容。
原因很简单:他们希望限制在服务器和浏览器之间来回发送密码的次数。这有助于限制某些系统的曝光。(link)
现在,显然,如果你正在使用ssl,那么这不是一个考虑因素。不幸的是,绝大多数站点仍然没有使用SSL,并且很乐意在数据库中来回发送数据。该字段在客户端和服务器之间传播的次数越多,获取FireSheep的机会就越多。
请记住,这并不是说有人在整个对话中听不到第一篇文章。但是,请将其视为限制(不消除)攻击面的简单选项。
下一个原因是几乎每次站点在提交后都向用户显示密码字段,这是因为验证没有通过。这可能意味着用户名和/或密码不正确。考虑到密码字段只向用户显示星号或点,没有真正的理由将其交还给用户。
鉴于您永远不想告诉用户哪些凭据失败(即:您不想说“密码无效”或“用户名无效”)并且普通用户无法确定他们是否发胖他们的进入,恕我直言,清除BOTH要好得多。
除此之外,你可以在这里选择。标准是将其删除。考虑到这是绝大多数网站的工作方式,你真的想要反对这种做法吗?就个人而言,我发现即使我们不同意它们,我们也更好地坚持使用UI标准。
用户已经有足够的时间使用所有不同的选项。
答案 1 :(得分:11)
@NickHeidke和@Chris Lively提交的答案都很棒,让我得出一些我想分享的结论。
首先,关于可用性:当表单未通过验证时,验证问题不是“密码”字段保留其值的唯一位置是“注册”表单与密码或确认密码有关。它绝对不适合“登录”表单,“更改密码”表单,或者可能是任何其他地方。因此,Html.Password
忽略ModelState
这一事实非常有意义。
其次,关于安全性:除非谨慎实施,否则“注册”表单将保存在浏览器的导航历史记录中。按“返回”将重新发送您的密码,这可能无法通过验证,并返回填写了密码的表单。密码填写的事实并非安全漏洞,因为它与浏览器已保存和发送的密码相同。您可以“查看源代码”以查看密码,但您也可以查看页面请求以查看密码(例如,使用FireBug)。
当然,当你看到填写的密码时,“查看源代码”会更容易也更明显,但我会说更好的解决方案是以一种未保存到的方式实现“注册”表单浏览器历史;例如,PRG Pattern with a Validation workaround,但这是一个完全不同的主题!
我的结论是:密码字段在显示时几乎总是清晰。 如果您想提高可用性并且不想让用户重新输入密码,请先尝试使用客户端验证! 最后,如果您真的知道自己在做什么,并且真的想提高可用性,那么可以在注册表单上保留这些值。但这可能不是最好的主意。
答案 2 :(得分:3)
我过去听到的解释是,如果用户点击提交并离开他们的计算机,其他人就不应该在他们不知情的情况下出现并重新提交
答案 3 :(得分:2)
@Scott Rippey给出的答案,真的解释了很多。 您不能保留@ Html.Password或@ Html.PasswordFor的值,因为它在帮助程序本身中是硬编码的。有关更多信息,请参阅此链接 retain password value.
解决方案: 您可以做的是将密码或密码替换为,
@Html.TextBoxFor(x => x.Password, new { type = "password" })
答案 4 :(得分:0)
虽然我同意在登录时这种行为是明智的,但在创建用户帐户时,它会觉得它提供了极差的用户体验。当表单上有许多字段并且用户在一个或多个字段中出错时,必须重新输入密码(新的和确认)非常烦人,并且当密码字段在视图中不可见而不滚动它时很容易忘记重新输入它们。