Should Password fields retain their values if a form does not pass validation?
I have a typical sign-up form with two password fields.
<form>
<%=开发者_StackOverflow中文版 Html.TextBox("Email", null) %>
<%= Html.Password("password", null) %>
<%= Html.Password("confirmPassword", null) %>
<input type='submit' />
</form>
If the form fails validation and is redisplayed, the text field retains its value but the password fields are always blank.
Why shouldn't the password fields retain their values? And more importantly, is there any reason I shouldn't override this behavior?
I feel like this behavior decreases usability, and would prefer password fields to behave the same way as textbox fields -- keeping the entered value when validation errors exist.
I'm using ASP.NET MVC, but this question pertains more to usability and security. I understand that what I'm seeing is expected behavior, and taking a look at the Password(...)
method shows me that it explicitly ignores the value in ModelState
.
You can send the value back on a regular input type=password field.
However, if you are using the .net input control, then it will clear the contents of value prior to sending the html back to the client.
The reason is simple: They wanted to limit the number of times in which a password was sent back and forth between the server and the browser. This helps limit exposure to some systems.(link)
Now, obviously, if you are using ssl then this isn't much of a consideration. Unforunately the vast majority of sites out there STILL don't use SSL and will happily send data back and forth in the clear. The more times that field travels between client and server, the more opportunities someone has of grabbing it ala FireSheep.
Bear in mind, this isn't to say that someone listening in on the whole conversation won't get it from the first post. However, consider it like a simple option to limit (not eliminate) the attack surface.
The next reason is that nearly every time sites show the password field to the user after a submit, it's because validation didn't pass. This could mean that the username and/or password is incorrect. Considering that password fields only display asterisks or dots to the user, there's no real reason to give it back to them.
Given that you never want to tell the user which of the credentials failed (ie: you do NOT want to say "password invalid" or "username invalid") AND that common users have no way of figuring out whether they fat fingered their entry, it's much better IMHO to clear BOTH.
All of that aside, you have a choice here. The standard is to blank it. Considering that this is the way the vast majority of sites work, do you really want to go against the grain? Personally, I find that we are much better off sticking to UI standards even when we disagree with them.
Users already have a hard enough time with all the different options available.
The answers submitted by @NickHeidke and @Chris Lively were both great and led me to a few conclusions that I would like to share.
First of all, regarding usability: the ONLY place where it might be appropriate for a password field to retain its value is on a "sign-up" form, when the form does not pass validation, and the validation issue is NOT related to the password or confirm password. It is definitely not appropriate for a "log-in" form, "change password" form, or probably any other place. Therefore, the fact that Html.Password
ignores the ModelState
makes perfect sense.
Second, regarding security: unless carefully implemented, a "sign-up" form will be saved in your browser's navigation history. Pressing "Back" will resend your password, which would probably fail validation, and return the form with your password filled out. The fact that the password is filled out is NOT a security breach though, because its the same password that the browser already saved and sent. You can "View Source" to see the password, but you could view the page request to see the password too (for example, using FireBug).
Granted, it is easier and more obvious to "View Source" when you see a password filled out, but I'd say the better solution is implementing the "sign-up" form in a way that isn't saved to browser history; for example, the PRG Pattern with a Validation workaround, but that is a whole different topic!
My conclusion is this: password fields should almost always be clear when shown. If you want to increase usability and don't want to make users retype their passwords, try to use client-side validation first! And finally, if you really know what you're doing, and really want to increase usability, it's ok to persist the values on a sign-up form. But it probably isn't the best idea.
The explanation I've heard for this in the past, is that if a user clicks submit and walks away from their computer, someone else shouldn't be able to come along and re-submit without their knowledge.
Answer given by @Scott Rippey, really explains a lot. You cannot retain the value of @Html.Password or @Html.PasswordFor because it is hardcoded in the helper itself. for more refer to this link. retain password value.
Solution: What you can do, is replace the Password or PasswordFor box with,
@Html.TextBoxFor(x => x.Password, new { type = "password" })
While I agree that when logging on this behaviour is sensible, it feel it provides an extremely poor user experience when say, creating a user account. When there are many fields on a form and the user makes a mistake in one or more fields, having to re-enter the passwords (new and confirm) is very very annoying, and when the password fields are not visible in view without scrolling it is very easy to forget to re-enter them.
精彩评论