Countdown Timer to activate a controller method - javascript

I am building a survey page where users have a limited time to answer all their questions. The time given is stored in the model as #test.time_allowed, which is an integer representing seconds.
I need to have a simple and non-user-tamperable way to get a timer to display on the view and execute a controller action when it winds down to 0. How can I accomplish this?
I'm a relative beginner so any specific answers would be really helpful. Thank you.
---UPDATE---
#Bryan:
I assume there is a tamper proof way if the timing is done server side? For example, there might be a javascript timer on the client side as you suggested, but upon submission can't the submission time be checked against the time of the window's initial load?

Since data coming back from the client can never be fully trusted, the server must somehow know what the timestamp of the originally generated form was. This could be done by saving variables in the session or database, but this is problematic. Instead, the server can place a timestamp in the form, either encrypted, or signed, to ensure the client has not altered it. The server can then reject the submission as necessary. On the client, separate logic can handle the UI portion, giving the user feedback on the time limit, but ultimately this only loosely coupled to the server handling.
Details:
The server should generate two form fields: one with the system timestamp time = Time.now.to_i to track when the form was generated, and another with a signature Digest::MD5.hexdigest(time.to_s.concat('Some-secret-string-1234')) (note using the same time value here for the timestamp form field and signature form field). This validates that the form is submitted with a server-generated timestamp that has not been altered by the client.
You might also send another form field with the time limit.
On the client, read the timestamp, use setTimeout and the time limit to generate a countdown or whatever you want to do on the front end.
When the form is submitted, authenticate the timestamp submitted with the form by regenerating the MD5 signature using the same method as before. Make sure it matches the signature submitted by the form. Then, add the timestamp to the timeout, and make sure it's later than the current server time. If so, you have a valid submission, within your time constraint.
You probably will need to give a little more leeway on the timeout at the server than on the client, maybe a few seconds, to account for network delays, otherwise the user might see one second remaining, click submit, and then by the time the server request is received, it will seem like the timer has expired.
Be sure to add require 'digest/md5' to get access to MD5.
Using MD5 signatures like this is a great way to verify that a client has not altered key parameters in a form in a stateless manner, whatever you would like them to be. A good addition to your bag of tricks.
Good luck!

There's no 100% tamper proof way of implementing this since you would need to do this using JavaScript which can be turned off or manipulated by a sufficiently malicious user.
However if you aren't concerned about these issues you could simply set a timeout on the page to submit the form after the number of seconds have elapsed. To do this you would need something similar to the follow. Obviously timeInMilliseconds would need to be generated into the page from the template on the server side.
window.setTimeout(function() {
document.forms['survey_form'].submit();
},
timeInMilliseconds);

Create model for ongoing surveys, and add after_create filter that will set deadline to Time.now + survey_duration. Keep logic that will deny late sending of answers in model.

Related

Quiz application in .NET MVC/JS/JQUERY, how to prevent cheating?

I'm making a quiz application, where 4 users join a lobby (finished), and then the leader starts the quiz.
When the quiz is started, questions get randomly selected. Users can answer them, and click submit. Each question is timed, meaning user only has 10 seconds to answer the question.
This is all done through AJAX, since I want the website to be real-time. How exactly would I prevent cheating? User could manually edit the JS file, etc.
I was thinking of getting the exact time when the question gets loaded + the answer time. And if it's not in the span of 10 seconds, he's cheating. Would that work, or is there a better and easier way to do this?
Thank you.
Edit
I thought AntiForgeryToken was right solution to solve your problem. I read a lot of articles to make sure my old answer is correct.
1- Hiding or Encrypting the javascript source code
2- How to Disable HTML view source or Encrypt Html elements programatically?
3- How To Prove That Client Side Javascript Is Secure?
4- ASP.NET MVC - does AntiForgeryToken prevent the user from changing posted form values?
I came to the conclusion:
AntiForgeryToken prevents a malicious site to trick a user to a form that looks the same as the original and post it to the original site. It does not prevent the scenario you are describing.
There's really no way to do this completely client-side. If the person has a valid auth cookie, they can craft any sort of request they want regardless of the code on the page and send it to your server.
You can use HtmlHelper.AntiForgeryToken with salt value.
To use these helpers to protect a particular form, put an Html.AntiForgeryToken() into the BeginForm, e.g.,
#using (Html.BeginForm("Users", "SubmitQuiz"))
{
#Html.AntiForgeryToken()
<!-- rest of form goes here -->
}
This will output something like the following:
<form action="/Users/SubmitQuiz" method="post">
<input name="__RequestVerificationToken" type="hidden" value="saTFWpkKN0BYazFtN6c4YbZAmsEwG0srqlUqqloi/fVgeV2ciIFVmelvzwRZpArs" />
<!-- rest of form goes here -->
</form>
Next, to validate an incoming form post, add the [ValidateAntiForgeryToken] filter to your target action method. For example,
[ValidateAntiForgeryToken]
public ViewResult SubmitQuiz()
{
// ... etc
}
Salt is just an arbitrary string. A different salt value means a
different anti-forgery token will be generated. This means that even
if an attacker manages to get hold of a valid token somehow, they
can’t reuse it in other parts of the application where a different
salt value is required.
You can create different salts for different users like this.
Edit
AntiForgeryToken() prevents tampering with the code using inspection tools like this:
In Client side
1- A new random anti-XSRF token will be generated.
2- An anti-XSRF field token is generated using the security token from step (1).
In Server side (Validating the tokens)
1- The incoming session token and field token are read and the anti-XSRF token extracted from each. The anti-XSRF tokens must be identical per step (2 client side) in the generation routine.
2- If validation succeeds, the request is allowed to proceed. If validation fails, the framework will throw an HttpAntiForgeryException.
For more information this, Please see this article.
Conclusion: Since there's no way to prevent anything on the client side, the only solution that actually sounds okay is having server check everything.
A GET request, which requests the question and logs the time. After that, a JS timer which automatically submits the question if the countdown is finished. The user can also manually submit the answer (obviously). POST of the answer, and the server logs the time of it, compares it to the initial time of the GET request. If it's longer than 10 seconds, it throws and error, and the answer is not counted.
Thank you everyone.

How do I prevent website user from seeing certain information until a certain condition is met.

So this is what I would like my website to do:
The website will generate a random number between 1 and 10,000.
The website user will then guess the number that the website generated by imputing their guess into a text-box.
If the user gets the number wrong a new number is generated and the user has to guess again.
If the user gets the number right a code-number is revealed.
My problem is that if the user simply inspects the java script they will be able to see the code-number within the script. How do i prevent the website user from manipulating the javascript code to know which number the website generated? also, how do I prevent the user from accessing the code by looking at the javascript? Do i need to use php or something?
Thanks for taking the time to read my question.
first of all you don't have to generate the number until they actually guess it.
function guess(number){
var rand=Math.random()*10000;
if(number==rand){
//success
}else{
//failure
}
}
This way no number is generated until they guess and you can't inspect that.
Also thinking outside the box: Based on the conditions, the number from the guess is irrelevant. If the number changes every time, they have a 1/10,000 chance every time to guess correctly. You simply have to write a function that only succeeds once every ten thousand times. However if they are looking at the source, they might feel betrayed by this.
If you put all your game logic on the client side, the client will be able to hack your game. All major web browsers come with a debugger which could easily manipulate and navigate your client side code in a variety of different ways.
That is why the server side should be responsible for these kinds of checks and validation. If the client had to submit the number to your server, the answer could be generated on the server side where it would be safe from any tampering.

MVC asp.net server side timer to prevent user from editing timer

I have a MVC asp.net quiz application. You have a variable amount of time to take the quiz, and if time runs out, then the answers are automatically submitted.
Currently, I have the timer setup in Javascript, with the amount of time being held in the Controller - Session["EndTime"]. But, my understanding is that a user can edit the Javascript and change the timer when it is implemented in Javascript. If true, how do I run the timer in the Controller and send an Action once the timer runs out?
The server can't force the browser to submit anything, that's what the JavaScript code would do. And, yes, the user can choose to modify that if he or she wants.
What the server would do is keep track of two things:
A unique identifier for that instance of the "test"
A date/time stamp of when the "test" began (or, conversely, when it expires, as either value carries the same amount of information)
The first value is included in the form sent to the browser, basically just a hidden form field. When a test result is posted to the server, the server-side code uses the identifier to look up the persisted date/time stamp to compare it with the current date/time. If more time than expected has elapsed, reject the test results with an error.
Basically, the server-side code can't force the user to submit the results. But it can reject results which aren't submitted in time.

Passing a JS variable to PHP Safely

I making a javascript game where the player builds up a score against a count down timer. When the timer runs out I display a form that show the score and lets the user enter they username (arcade style). I'm going to use the POST method send the user score to a php file that will store it somehow (database,textfile. or something). How do I prevent people from fiddling with the JS code and passing some new value thru that isn't the correct score (or something that isn't malicious).
At the very least, what are the safest methods on the PHP/reviving end to at least only accept and integer value?
That's a well known and difficult problem. I'm not sure it ever has a good solution. The user is the client is JS, so they have 100% control over what's sent to the server.
The only thing you can do and force, is server side validation. Don't just send the score. Send the path, the method, the steps, etc. Starting a session/game/level should also happen on the server, because the timestamp could be faked from the client.
You can make the whole game in JS, but start and end it on the server and remember all the steps. This might mean double step/path validation: JS (instantly) and server.
(I had the same problem with http://games.webblocks.nl/110 which stores steps (clicks) in g_stack.)

How to prevent the clientside user from changing arguments in an onClick function?

I just realized while testing an onClick function with firebug that it would be really easy for a user to change the value of the arguments being passed. This could mess thins up.
Is there any easy way to prevent this, especially when arguments need to be passed?
It is impossible. The code is executing on the user's computer. They are in control.
If they edit it and "mess it up", then that is on their head.
If they edit it and it submits an HTTP request to your server, and your server allows (for instance) that request to delete data belonging to another user then the problem is that your server didn't check that the user submitting the request had permission to delete that data before following through.
You cannot trust anything sent from the client. The user might hand-edit the URL arguments, or a script kiddie could send you a request not even using a browser at all. You must validate everything server-side.
No, this simply can't be done.
Once the script is loaded to the client's machine. He can use/modify it, as he wants.
I'd recommend validating the arguments against expected set of values, and/or business rules wherever the results are being processed (client/server). Ideally validation checks happen on the server where the user has no control. Validation on the client side could even be modified to allow invalid data entry.
There is no way to completely control it - only validate it based on criteria.
You can't prevent this action because JavaScript is a client side . Also you can never trust the client .
You should make a validation for any request at server side to protect your data against client misuse .
you can somehow make it hidden from client eyes
by using .delegate()
EX.
$("table").delegate( "td","click", function() {<br>
// write here your function<br>
});
The client can execute this script but it isn't direct in front of his eyes ..

Categories

Resources