Form retaining values after refresh - ruby-on-rails

So I've inherited this legacy rails codebase and there's a bug i need to fix where a given form is retaining values (that have not yet been saved to the DB) even after Page Refresh.
Use Case:
User fills data in form but does not press submit.
User Clicks refresh button on browser.
The Values in the form are retained instead of refreshing the whole page.
Any ideas where I can start looking? In my brief, limited Rails experience, this is not the sort of thing that happens by default, so it must be coded somewhere?

Sometimes browsers will do this. (I'm not talking about auto-fill drop-downs, which browsers also do... just talking about forms that are partially filled out, never submitted, and are then refreshed).
Make sure the values in the fields are actually coming from your Rails app by checking the HTML source window.
Values provided by the browser due to previous entry won't be in the VALUE attribute, but server-provided ones will be.
Some options for avoiding this might be:
Send the user to the form using a POST. Thus, any refresh results in a "do you want to resubmit" etc. I don't think the browser will pre-fill any fields in this situation (same as when a user posts and then hits the back button).
Use the onload() event to wipe out the form field values.
There's probably a simpler solution... Ctrl-F5 sometimes does the trick, but I think I've seen even that not work before.

Tell user to press CTRL+F5
--
edit
if you can't tell the user to press CTRL+F5 (which always in my experience works unless the browser is buggy, or unless something else is going wrong), just trip form.reset() in the onload event. This will clear the fields in the form to the default values. If you have default values in the fields though, (like <input type="text" value="enter name here" />) then when you trip .reset(), it will reset to the default value.

I just ran into this problem as well, and even <body onload="myform.reset()"> didn't work. This was particularly a problem because, for better or for worse, I'm using hidden inputs as counters (to keep track of a dynamic number of file upload fields, for example). These obviously need to be reset on reload to keep non-applicable warning messages from appearing. I "fixed" it for my in-house purposes by abandoning the reset button in favor of a link. Instead of <input type="reset"/> I'm using Reset (the filename is index.php). Far from elegant, but it works for my purposes.

I ran into this issue with a Rails 7 app. When navigating to a view with a form everything is blank, when I hit refresh all the inputs get filled by the browser (not by Rails). To keep the inputs blank I used the autocomplete attribute, which is supported by all modern browsers:
<!-- for the whole form -->
<form method="post" action="/form" autocomplete="off">
<!-- for a specific input element -->
<input type="text" id="foo" name="foo" autocomplete="off">

Related

Hidden field vulnerability

I have completed the source code scan (ASP) using the Fortify source code scanner.
Many hidden fields shows as a vulnerability. Like this one:
<input type="hidden" name="ToSave" value="0" />
How do I fix this issue to receive a passing test?
Thanks in advance
Mahesh
If this is application state and is not modified by the user:
Passing application state thru the browser is always a bad idea and is one of the first things that the hacker will exploit.
If this is application state: use proper ASP session management and save the session state on the server when you send the page to the user, and look up the session state on the server when the request is returned. In ASP.NET with C# you might do something like this:
Session(“ToSave”) = false;
When you send the response to the browser (e.g. send the page). Then, when you get the request back, because you’re using ASPs session management, session will have the state that you set.
If this is not application state but is a hidden field that is calculated by JavaScript in the browser and is used on the server side:
Please look at the design of the application. I do a ton of these code reviews and usually find that the application is doing something in JavaScript that should only be done on the server side. One example would be calculating the score of a test on the form putting that score in a hidden field and accepting that field on the server. Another example would be calculating the ‘next’ page in a flow and putting a marker in a hidden field. If you want to provide something like a score on the browser for user convenience use that's fine but make the official calculation (and decision, if applicable) on the server.
An attacker can easily see these values and create a request that would break your application, or worse, get the attacker something that he or she did not deserve.
In any case hidden fields are cached on the browser just as any pages are cached so it might not be wise to use hidden fields if they contain data you expect the user to not be able to see.
So, bottom line, I would agree that you shouldn't use hidden fields.

ASP.NET MVC 4.0 Chrome Caching

I have code in place to disable caching in my MVC application. I'm using the following response headers. They seem to work in all browsers except for Chrome (currently using version 31.0.1650.48). Users are able to submit a form with model values. When they hit the back button I need the page to reload with a blank model. The headers appear to partially work since the request is hitting the action and returning the blank model. However the view isn't updating. The values from the previous post are being retained. I've tried clearing the ModelState but that doesn't work. Any suggestions? Thanks in advance!!
filterContext.HttpContext.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1))
filterContext.HttpContext.Response.Cache.SetValidUntilExpires(False)
filterContext.HttpContext.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches)
filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache)
filterContext.HttpContext.Response.Cache.SetNoStore()
Turning off autocomplete for the form fixed this for me. I appreciate all the input!
<form autocomplete="off"></form>
There is a way to do this in javascript for everything in one go like so...
document.getElementById("YourFormID").reset();
Just add an id to your form and all your inputs will reset on page load. Regardless if its a first time visit or a back button click with the page being cached. The biggest difference from your solution and this is that "the autocomplete attribute is new in HTML5". Which means it is not supported in older browsers, and though it does what you want it also prevents the user from autofilling fields. Meaning that for example on text types inputs users will not see a suggestion of words they may have entered on previous or other pages. You can see an example here.

How does Rails persist text in input field?

I have a regular text input field, whose value is submitted via AJAX. After I migrate away from this page, and hit Back button, I can still see the value of the field there.
My questions are:
Does most of modern browsers support this user-entered values?
How can I remove the persisted value using Rails?
Thank you.
Your browser is remembering the form input values and displaying them when you go back. This likely doesn't have anything to do with Rails*.
You can't really do anything via Ruby/Rails code to change this behavior, but you can do it with JavaScript. Here's a random SO question that covers it: Reset form on Back button.
I'm not sure if there's a perfect way to handle this in every browser. Also note that many users would prefer that the browser keep the form values they've entered.
Note: I only qualify with "likely" because it is possible to write an app that explicitly remembers form values and restores them when the page is visited again, but by default, Rails isn't going to do that. It'd involve a fair bit of Rails and JavaScript code.
Does most of modern browsers support this user-entered values?
Yes, I believe they all support it to various degrees
How can I remove the persisted value using Rails?
This is a client side issue, not a Rails issue. You could use javascript to clear the input fields
A similar question and answer: Clear all fields in a form upon going back with browser back button
BFCache? https://developer.mozilla.org/en-US/docs/Working_with_BFCache

Disabling "Remember My Password" prompt to users visiting site

So I have an ASP.Net MVC site and I was wondering if it was possible at all to make it so users will have to enter in their passwords manually so its not auto filled for them by the browser? It seems like a simple thing to ask, but googling this I just get instructions on how a client can disable their prompt.
I've never used it for this, but there is an autocomplete property that when disabled will tell the browser not to store any information from the password field :
If AutoComplete is disabled, values
are not stored and suggested values
are not presented.
http://msdn.microsoft.com/en-us/library/ms533486(VS.85).aspx
<INPUT TYPE="password" AUTOCOMPLETE="off">
I've used it for normal text fields for credit card numbers and such. But I didn't realize this would work for the password fields as well. You might want to try it in other browsers besides IE though to be sure.
UPDATE: Looks like this works in both Firefox and Chrome.
If you explicitly set value="" It will not be remembered. This is how my bank does it. You can also set the autocomplete property.

Preventing double HTTP POST

I have made a little app for signing up for an event. User input their data and click "sign me in".
Now sometimes people are double in the database, the exact same data that got inserted 2 times very quickly after each other. This can only mean someone clicked the button twice, which caused two posts to happen.
This is common web problem, as credit card apps and forum apps often say: "Clicking once is enough!".
I guess you could solve it by checking for the exact same data to see if the post is unique, but I wonder if there are other methods.
This ofcourse does not count for ASP.NET webforms, because POST doesn't matter as much.
While JavaScript solutions can disable the submit button after it has been clicked, this will have no effect on those people who have JavaScript disabled. You should always make things work correctly without JavaScript before adding it in, otherwise there's no point as users will still be able to bypass the checks by just disabling JavaScript.
If the page where the form appears is dynamically generated, you can add a hidden field which contains some sort of sequence number, a hash, or anything unique. Then you have some server-side validation that will check if a request with that unique value has already come in. When the user submits the form, the unique value is checked against a list of "used" values. If it exists in the list, it's a dupe request and can be discarded. If it doesn't exist, then add it to the list and process as normal. As long as you make sure the value is unique, this guarantees the same form cannot be submitted twice.
Of course, if the page the form is on is not dynamically generated, then you'll need to do it the hard way on the server-side to check that the same information has not already been submitted.
Most of the answers so far have been client-side. On the server-side, you can generate a hidden field with a GUID when you first produce the form, and then record that GUID as a submitted form when the post is received. Check it before doing any more processing.
Whenever a page is requested from the server , generate a unique requestToken , save it in server side,mark status as NOT Processed and pass it along with the current requested page. Now whenever a page submit happens , get the requestToken from the "POST"ed data and check the status and save the data or take alternate action.
Most of the banking applications use this technique to prevent double "POST"ing.So this is a time proven & reliable way of preventing double submissions.
A user-side solution is to disable the submission button via Javascript after the first click.
It has drawbacks, but I see it often used on e-commerce websites.
But, it won't never replace a real server-side validation.
Client side techniques are useful, but you may want to couple it with some server side techniques.
One way to do this is to include a unique token in the form (e.g. a GUID or similar), so that when you come to process the form you can check to see whether the token has already been used, preventing a double submission.
In your case, if you have a table with event visitors, you might include this token as a column.
A client-only solution won't be enough, as stated in many of the answers here. You need to go with a server-side fail-safe.
An often overlooked reason that disabling the submit button doesn't work is, the user can simply refresh the submit target (and click OK on the "are you sure you want to resubmit the POST data?" dialog). Or even, some browsers may implicitly reload the submitted page when you try to save the page to disk (for example, you're trying to save a hard-copy of an order confirmation).
Almost no one has js disabled.
Think about coding your e-commerce website for the 70 year old woman who double clicks every link and button.
All you want to do is add a javascript to prevent her clicking "Order Now" twice.
Yes - check this at the server side too "be defensive" - but don't code for that case. But for the sake of a better UI do it on the client side too.
Here are some scripts that I found:
//
// prevent double-click on submit
//
jQuery('input[type=submit]').click(function(){
if(jQuery.data(this, 'clicked')){
return false;
}
else{
jQuery.data(this, 'clicked', true);
return true;
}
});
and
// Find ALL <form> tags on your page
$('form').submit(function(){
// On submit disable its submit button
$('input[type=submit]', this).attr('disabled', 'disabled');
});
None of the solutions address a load-balance server.
If you have some load balancer, send a UUID (or any type of unique number) to the server to store and read again will not work well if the server is not aware of other servers, because each request could be processed by a different server in a stateless environment. These servers need to read/write to the same place.
If you have multiple servers you will need to have some shared cache (like a Redis) among the servers to read/write the unique value in the same place (what could be an over-engineering solution, but works).
Client side alteration is a common technique:
Disable submit button
Change the screen to a "please wait" screen
If the form was modal, changing the screen back to their usual process (this has the benefit of making things look really slick)
But it's not perfect. It all relies on JS being available and if that's not the case, without back-end duplication detection, you'll get duplicates still.
So my advice is to develop some sort of detection behind the scenes and then improve your form to stop people with JS being able to double-submit.
You can track the number of times the form's been submitted and compare it to the number of unique visits to the page with the form on it in the session.
Beside the many good techniques already mentioned, another simple server-side method, that has the drawback of requiring a session, is to have a session variable that is switched off on the first submit.

Resources