I'm actually working on a website that should host a sort of maths competitions. Every game has its own page and its own start and term.
Currently in every page I'm managing the time with a javascript function. Something like this:
var start = new Date(/*date of start*/),
end = new Date(/*date of end*/);
function timeControl() {
var now = new Date;
if (now<start) {
//case 1
} else if (now>start && now<end) {
//case 2
} else {
//case 3
}
}
setInterval(timeControl, 1000);
My problem is that JS is run by client, so users potentially can handle the mechanism and simulating all possible cases in every moment.
The question is: how can I prevent the handling by users? Obviously I mean not in JS because I think in JS isn't possible...
This is a super-broad questions, since how exactly it could be done depends on a lot of factors - which backend do you have, how well do you know it, what are exact requirements to what should happen in what case and so on.
But as a general idea, everything that is on a client side, can and will be manipulated by a client, no matter how well you do that, so your only hope is doing all this logic on a server.
In your case it might be something like this:
When showing a page with a contest to a client, record (on server side!) the timestamp you served it to him.
When client submits a solution, check (again, on server side!) difference between current timestamp and timestamp he was served the timestamp.
On client side you might add some logic to track & hide some content after allowed time expires, and it will work in 99% cases, but as you have already discovered, this will be tampered with and as such, you can regard it only as cosmetics to spice things up.
Related
Let's say my website uses a 3rd party javascript library which requires the user's system time to be correct (synced with the server time) within a couple minutes.
Surprisingly many users have their device clocks set wrong by more than a couple minutes and are unable and/or unwilling to fix it. Is there any way I can fix it for them, at least inside a browser session?
I know how to get the correct time, but how can I "set" it into the browser session, so that it can be returned next time a 3rd party library asks for the current time?
For example, I would like to have something like this in my code:
let tWrong = new Date(); // contains wrong system time that the user has on their device
let tCorrect = getCorrectTimeFromServer(); // contains correct time fetched from a server
Date.someFunctionToSetGlobalTime(tCorrect); // how to do this?
And then, somewhere deep in the 3rd party library where I do not have access to change the code, this would happen:
let t = new Date(); // t already contains the correct server time
And if this is not possible, how do websites normally deal with this issue? It must be incredibly common, for example when issuing JWT tokens with an expiry time, that one side thinks the token is already expired as soon as it is issued, due to wrong system time.
Answering my own question, in case someone runs into the same problem.
I found out the 3rd party library was using the getUTCHours, getUTCMinutes and getUTCSeconds functions, so instead of setting the time itself, I ended up overriding these functions like this. It feels ugly, but it works:
Date.prototype.getUTCHours = getMyCorrectUTCHours;
Date.prototype.getUTCMinutes = getMyCorrectUTCMinutes;
Date.prototype.getUTCSeconds = getMyCorrectUTCSeconds;
The situation:
I have a program that records student's payments, (made entirely with HTML, CSS and javascript), I would like it to calculate the amount of students that stopped the lessons, automatically, around the end of the month (by automatically I mean without the user having to press any buttons to get that info).
My question is:
If for example I schedule the function to run on the 29 of every month, and that day the user does not open the program, does the function get executed anyway or not?
The program is an off line program, made to be downloaded once and run always, no need to connect again to the web if the user decides it.
I would do something like:
var thisMoment = new Date(),//creates a date object
currentDay = thisMoment.getDate(); //this would give me the day at that moment.
if(currentDay == 29) { }//code to be executed here
I know I could just try it, but I would have to wait for a day, or rewrite the code to schedule something some minutes ahead, but I would miss all the juicy information you are probably going to share here hahaha.
Any help appreciated! :)
Unless there's some sort of server-side component, your HTML app effectively ceases to exist as soon as the user closes it. Nothing will happen if it's not open.
To do this kind of thing, you will either need a server application that's continuously running, or some sort of cron job that runs an application/script on the server at the desired time. Then, you will need to have your frontend application communicate with this server, most likely through some kind of REST API.
I want to measure the time it takes for a user to complete a task (answer a quiz). I want to measure it accurately, without the network lag. Meaning, if I measure on the server side the time between 2 requests, it won't be the real time it took the user, because the network time is factored in.
But on the other hand, if I measure in javascript and post the timestamps to the server, the user will be able to see the code, and cheat by sending false timestamps, no?
How can I get the timestamps in javascript and make sure the user doesn't fake it?
Generally in client side code, any question that starts off with "How to securely..." is answered with "Not possible". Nothing, not even putting variables in a closure (because I, the evil cheating user could just change the code on my end and send it back to you).
This is the kind of validation that should be performed server side, even with the disadvantage of network latency.
The trick here would be to measure the time using JavaScript, but also keep track of it using server-side code. That way, you can rely on the timestamps received by the client as long as you enforce a maximum difference between calculated times. I'd say a few seconds should be good enough. However, by doing so, you are creating an additional vector for failure.
Edit: A user could potentially tweak his or her time in their favor by up to the maximum enforced difference if they are able to take advantage of the (lack of) network lag.
I faced same problem while designing an online examination portal for my project.
I went for a hybrid approach.
Get time from server as user loads the page, and starts timer based on javascript. Record the start time in your database.
Let the timer run on client side for some time, say 30 seconds.
Refresh timer by making a AJAX call to server for timer reset as per the time that has passed already.
NOTE: try to use external javascript and obfuscate the code of timer to make guessing difficult.
This way you may not prevent user completely from modifying timer, but you can limit max possible error to 30s.
Any player can easily cheat on this game by changing the amount of cupcakes through the browser console. I wanted to know if there was a way to prevent the user from doing so. This is also posted on github.
var numberOfCupcakesDisplay = document.getElementById("numberOfCupcakes");
var cupcake = document.getElementById("cupcake");
function updateValues() {
numberOfCupcakesDisplay.innerHTML = amountOfCupcakes.toString();
//displays number of cupcakes to screen
document.getElementById("amountOfToasters").innerHTML = amountOfToasters.toString();
//displays number of toasters to screen
document.getElementById("toasterButton").innerHTML = "        " + Math.round(costOfToasters).toString() + " cc";
//changes cost of toaster every time it is bought by 110%
}
cupcake.addEventListener('webkitAnimationEnd', function(e){
e.preventDefault();
this.style.webkitAnimationName = '';
}, false);
function clickCupcake() {
++amountOfCupcakes;
cupcake.style.animation = "shiftCupcake";
cupcake.style.webkitAnimationName = "shiftCupcake";
}
updateValues();
Yeah!! As other answers mention it is IMPOSSIBLE to prevent users from changing the values from browser console. In other words, You are simply asking How to write JS code so that user can not debug it. You can always use some methods which make life hard for people who want to cheat on the game.
1.Obfuscate the code.
Look at these links for more information on obfuscation.
SO: How to obfuscate Javascript
Jsobfuscate.com
2.Do not store the game's control values in global variable.
Do not store control values in global variables. Instead define a class and have these variables as private to it So that user has to dig in deep in order to find out where to put the breakpoints.
3.Minify/Compress your javascripts.
Obfuscation more or less covers minification as well.
You cannot prevent this. The best you can do is minify the JS so it's harder for players to find the right values to change. In fact, you can't prevent this with any game or indeed application; the user's computer controls all of the information so they can do anything they want to it.
The only way to be secure against this is to do all of the processing on a server you control. Even though, players can lie about their input data (hence aimbotting or other hacks).
by changing the amount of cupcakes through the browser console
Well, technically you can prevent this by creating a new scope:
(function(){
var cupcakes = 10;
})();
console.log(cupcakes); // ReferenceError: cupcakes is not defined
But note that there are still ways to "cheat," even with this protection (i.e. edit the JS source code). And if you are sending the result to a server... well, that will be even harder if not impossible to secure, since you can easily send a simple HTTP request via XMLHttpRequest.
There may actually be a way to reach your goal. But it depends on the game's logic.
If you can simulate the game on your server, you can generate random IDs for the cakes and when the game creates a new cake (on client), it would request an ID for it. Later when the cake is "destroyed", it would contact the server and provide it with the cake's ID. The final score is then computed on the server from the IDs it received.
This way you can track what was actually done by the user.
But an adversary can listen the network requests and determine the request for creating a new ID. The same way he can determine the request to tell the server this ID has been "destroyed".
If your game logic allows, you can e.g. tell the server to only generate one ID every 5 seconds or so. You can also mark as spoofed all results where all cakes were "destroyed" and none was missed (if the game is difficult enough).
So, it's still not 100% secure, but you might be able to reach a relatively high level of spoofing protection. On the other hand, it adds a lot of code complications and you must weigh the pros and cons.
It's a simple case of a javascript that continuously asks "are there yet?" Like a four year old on a car drive.. But, much like parents, if you do this too often or, with too many kids at once, the server will buckle under pressure..
How do you solve the issue of having a webpage that looks for new content in the order of every 5 seconds and that allows for a larger number of visitors?
stackoverflow does it some way, don't know how though.
The more standard way would indeed be the javascript that looks for new content every few seconds.
A more advanced way would use a push-like technique, by using Comet techniques (long-polling and such). There's a lot of interesting stuff under that link.
I'm still waiting for a good opportunity to use it myself...
Oh, and here's a link from stackoverflow about it:
Is there some way to PUSH data from web server to browser?
In Java I used Ajax library (DWR) using Comet technology - I think you should search for library in PHP using it.
The idea is that server is sending one very long Http response and when it has something to send to the client it ends it and send new response with updated data.
Using it client doens't have to ping server every x seconds to get new data - I think it could help you.
You could make the poll time variable depending on the number of clients. Using your metaphor, the kid asks "Are we there yet?" and the driver responds "No, but maybe in an hour". Thankfully, Javascript isn't a stubborn kid so you can be sure he won't bug you until then.
You could consider polling every 5 seconds to start with, but after a while start to increase the poll interval time - perhaps up to some upper limit (1 minute, 5 minute - whatever seems optimal for your usage). The increase doesn't have to be linear.
A more sophisticated spin (which could incorporate monzee's suggestion to vary by number of clients), would be to allow the server to dictate the interval before next poll. The server could then increase the intervale over time, and you can even change the algorithm on the fly, or in response to network load.
You could take a look at the 'Twisted' framework in python. It's event-driven network programming framework that might satisfy what you are looking for. It can be used to push messages from the server.
Perhaps you can send a query to a real simple script, that doesn't need to make a real db-query, but only uses a simple timestamp to tell if there is anything new.
And then, if the answer is true, you can do a real query, where the server has to do real work !-)
I would have a single instance calling the DB and if a newer timestamp exists, put that new timestamp in a application variable. Then let all sessions check against that application variable. Or something like that. That way only one innstance are calling the sql-server and the number of clients does'nt matter.
I havent tried this and its just the first idéa on the top of the head but I think that cashe the timestamp and let the clients check the cashe is a way to do it, and how to implement the cashe (sql-server-cashe, application variable and so on) I dont know whats best.
Regarding how SO does it, note that it doesn't check for new answers continuously, only when you're typing into the "Your Answer" box.
The key then, is to first do a computationally cheap operation to weed out common "no update needed" cases (e.g., entering a new answer or checking a timestamp) before initiating a more expensive process to actually retrieve any changes.
Alternately, depending on your application, you may be able to resolve this by optimizing your change-publishing mechanism. For example, perhaps it might be feasible for changes (or summaries of them) to be put onto an RSS feed and have clients watch the feed instead of the real application. We can assume that this would be fairly efficient, as it's exactly the sort of thing RSS is designed and optimized for, plus it would have the additional benefit of making your application much more interoperable with the rest of the world at little or no cost to you.
I believe the approach shd be based on a combination of server-side sockets and client-side ajax/comet. Like:
Assume a chat application with several logged on users, and that each of them is listening via a slow-load AJAX call to the server-side listener script.
Whatever browser gets the just-entered data submits it to the server with an ajax call to a writer script. That server updates the database (or storage system) and posts a sockets write to noted listener script. The latter then gets the fresh data and posts it back to the client browser.
Now I haven't yet written this, and right now I dunno whether/how the browser limit of two concurrent connections screws up the above logic.
Will appreciate hearing fm anyone with thoughts here.
AS