How I can know if a click event was generated by the user? (They used the mouse).
The opposite would be a click event triggered by a piece of JavaScript.
Think in a JavaScript library that displays advertisements. You wont want that anyone who uses the library fool you.
You need to make sure that the event is not forged.
Client code can never be trusted by the server. Anyone can open up their browser console and totally change the code.
You might be able to do different things to confuse robots or automated scripts, but you're helpless if you are trying to prevent a forgery that targets your site specifically.
To be honest, ANY attempt to making this tamper-proof will fail unless you follow these pretty simple advises:
don't do anything client-side, this problem family is a cognate of security, so you want to do everything server-side without relying on anything on the client;
don't trust the input you receive, doubt about its origin (e.g. user-agent, cookies, HTTP request, ecc. may all be forged into a key that perfectly fits your keyhole);
you do not really want to detect a mouse click, what you want is discriminate between human and machine, so use common techniques for that problem;
a CAPTCHA or other task that is currently next-to-impossible to solve for machines allows you to distinguish a real human from a machine.
That said, the easiest for your use case (advertisement) is a floating button embedded in an image that randomly changes position. On click you send the coordinates and a code that you use server-side to reconstruct the position of the button and thus if the coordinates are inside the buttons boundaries.
A machine will send wrong (random) coordinates with the code and server-side you will discriminate it because the click was not inside the boundaries.
This solution obviously can be enhanced:
smaller button on larger image (lower probability to have a lucky "false positive");
move the button over time (this requires an SWF plugin or HTML5 canvas);
avoid contrast that may be exploited to find the button in the image (e.g. a red button over a blue sky).
All you have to do is go to any website that has advertisements and look what they do: SWF plugins with micro-games that entice you to click it.
BTW: I don't like advertisements on web pages so maybe it's better you don't even implement that stuff...
You can check if the string 'Mouse' is found within the string representation of e.toString():
document.addEventListener('click', function(e){
console.log(e.toString().indexOf('Mouse') !== -1)
});
If the event was generated by code then e.toString() returns [object Event], but if it was a real mouse event it would return [object MouseEvent]. All I am doing is checking whether 'Mouse' is in that string to determine if it was indeed a real mouse click.
You might want to try like this:
document.addEventListener('click', function(e){
var w=[]["filter"]["constructor"]("return this")();//returns window, thanks to JSFuck
console.log(e instanceOf MouseEvent && e.view==w && e.srcElement && e.srcElement.ownerDocument.parentWindow==w && e.target && e.target.ownerDocument.parentWindow==w);
});
It checks if it is an instance of the MouseEvent object, then checks if the window is the same, the e.srcElement exists and if it is in the same window and if e.target exists and is in the same window.
Related
I'm building a simple HTML page, and I have an input field followed by a search button; this is the code:
<input type="text" id="sfield" placeholder="Write something">
<button id="search">Search!</button>
I'm currently writing the javascript to assign some actions to the button and to the input field, when I thought that it would be a good idea to add a feature that needs the cursor to be on the field for the search to start. I'll explain it better: if someone wants to search something, it will appear just like a normal input field and work like that. However, if someone tries to launch a script for auto-submitting the form, it'll act like no input was inserted.
For example, if someone tries to inject this script:
document.getElementById('sfield').value="Some stuff";
document.getElementById('search').click();
the search would start but the "Some stuff" string wouldn't be saved, as if the user clicked the search button without writing in the search field. Furthermore, adding the line
document.getElementById('sfield').focus();
should also do nothing, so that the only way to put the cursor in the field would be a manual action by the user.
I'm wondering if it's possible to make such thing; I already managed to get the search field blank with EventListener, but I don't have a clue about making the script discern whether the user put the cursor on the field or not.
I'd prefer not using JQuery but it's ok also with it. Any idea would be greatly accepted. Thanks.
In that case, the program needs to retain state. I'd do it like this...
http://jsbin.com/hopicucuyi/edit?js,console,output
<input type="text" id="sfield" placeholder="Write something" data-validated = "false">
<button id="search">Search!</button>
<script>
const inputField = document.getElementById('sfield');
const searchButton = document.getElementById('search');
inputField.onfocus = () => {
inputField.setAttribute("data-validated", "true")
}
searchButton.onclick = () => {
const isValidated = inputField.getAttribute("data-validated");
console.log('Is Validated: ' + isValidated);
}
</script>
Generally neither of these solutions will stop a bot that uses a browser (which is a bot that runs javascript). There is no 100% solution, but there are stronger solutions than checking if something has focus or not. Remember the javascript environment is completely controllable from the browser side of things. For instance, all I would have to do to get past your security is change the state of the input in question to data-validated="true" and your security falls apart.
However, the browser vendors have taken this possibility into account and provide you with a little-known solution. Look at the event data coming from a mouse click or a keystroke. This event data can be generated. It used to be easier in the older browsers to spoof an event just by using new Event(), but now modern browsers use specific events for keyboard and mouse. The part that makes spoofing these very hard is that in the event there are properties that are read-only. More specifically there is an event property called "trusted" that cannot be set by javascript. If you spoof a MouseEvent or KeyboardEvent, the "trusted" property is set to false, but if you use the actual mouse or keyboard "trusted" is set to true.
Info on the isTrusted property here: https://developer.mozilla.org/en-US/docs/Web/API/Event/isTrusted
Note: this is also not 100% as the bot can run a keyboard/mouse macro that creates genuine "trusted" events. However, it does make the system much harder to crack as many people dont know about this security trick, and most bots will not have mouse/keyboard control built in. If you encounter a bot that uses mouse/keyboard, you've reduced the security playing-field and further analysis of the events and interface usage can take place.
If you combine this method with other methods like browser fingerprinting etc. it makes your overall anti-bot security that much stronger and discourages many more possible bots.
Edit: Don't just use this method and others, obfuscate your code so that any attacker will have to take the time to deobfuscate and wade through a bunch of poorly labeled functions and encrypted strings if they want to see how your security works.
This is a fairly straight forwards question, but I cannot find the answer in the documentation.
I know it is possible to detect clicks, but is it possible to detect a key press using an InDesign script?
For example, if the user creates a text box, and types 'a' into it, I would like to capture that and do something with it.
Perhaps this can be done using hotkeys, where for example one script on startup adds a hotkey for each keyboard button, each hot key fires a script for handling it. This seems a bit of a hack (if it would even work). Is there not a on key press listener I can add?
Any help is much appreciated.
I have found this so far in the documentation:
Most of the things scripting cannot do—like setting up a workspace or
defining a set of keyboard shortcuts—are things that have to do with
the user interface.
For the specific example you give (typing something into a text frame), you can use the afterSelectionChanged event listener (whose parent can be the application, or a layout window, amongst others).
as the title says, i would like to know if theres any possibility in javascript (jquery) to check if there is any action in the document, and if not. something like a screensaver should pop up!
if someone is on the page and looks here, looks there and after a while he doesnt do anything, the mouse (or touch finger) stands still, i want to say the document after a minute without activity...
function noactivity() { //after 60000ms start something here }
i want that global for the whole document!
thanks ted
It can be done relatively simply in jquery using:
setTimeout();
http://jsfiddle.net/bernie1227/hNkTy/1/
I had this issue a while back while I was working on an iframe resizing issue. What I wanted was to tell the parent page whenever there is a change in height of the document.
What I found was that jQuery does not give such facility directly. The main reason for this is that there are too many activities happening to DOM which are not visible, when you are watching it (bind). You could however watch for a specific property like mouse moving on a document.
$(document).mousemove(function(e){
console.log(e.pageY);
console.log(e.pageX);
});
But then again that does not at all mean that the user is interacting with your page. That merely signifies that the user is on your page and his mouse is moving. The user might also be not moving the mouse and merely using his keyboard to interact with your page. So now you would have to watch for keyboard interaction aswell.
$(document).keyup(function(e){
console.log('active');
});
Using these you could create a countdown function which checks for a flag after a set interval of time. You could set the flag if user makes an activity. And after a set amount of time that function the 'noactivity()' function id the flag has not been set.
Another approach to watching the document activity could be you watching the DOM subtree being modified.
jQuery(document).bind('DOMSubtreeModified', function() {
console.log('active');
});
This works for Chrome/FireFox/IE8+ but not on Opera (any version). The main reason being that the operation is too heavy on your browser's resources. And I would discourage using this approach because listening for DOM mutation events may harm performance and the relevant W3C working groups are trying to find a better way to do this and deprecate DOM mutation events for this reason - it's hard or impossible to make a good and performant implementation.
I am not saying that the other options that I mentioned above are good either. They are also expensive operations if you are watching document and should be avoided. Another issue with those options is that the iframe content is not particularly the part of your document and these options will not work if user is interacting with iframe content.
So the conclusion is that W3C did not yet finalize a cheap way where user can watch changes in document subtree.
Examining our web logs we find a significant number of clicks are other double-clicks, or repeat-clicks (e.g. when the system is busy and has not reacted quickly enough).
Double-Clicking a SUBMIT button may cause a form to process twice (generally we program against this, but I'd like to avoid possibility of errors that we have not programmed against), but even double clicking a link means that the server has to process the response twice (usually the server will detect a "disconnect" on the first click and abort processing for that - but we still incur the server-time for the effort, which is compounded when the server is under heavy load).
Having said that, there are times when I never get a response to a click, and its only the re-click that works.
One action we do see is a mis-click - click on a link, realise that it was not the desired link, and then click on the correct, adjacent, link - clearly we still need to allow that.
How do you handle this / what do you suggest? and what is the best way to achieve this, generically, across the whole application?
1) We could disable the link/button after click (perhaps for a set period of time, then re-enable)
2) We could hide the "body" of the page - we have done this in the past, just leaving the "banner" pane (which looks the same on all pages) which gives the appearance of the next page loading (but does not play well with the BACK button in some browsers) - this also mucks up users who mis-clicked
You could do this with a combination of delegate and data:
$(document).delegate('a, :button', 'click', function(e) {
var lastClicked = $.data(this, 'lastClicked'),
now = new Date().getTime();
if (lastClicked && (now - lastClicked < 1000)) {
e.preventDefault();
} else {
$.data(this, 'lastClicked', now);
}
});
This will prevent constant rebinding, so should have decent performance.
You can set custom attribute once the element is clicked then check for that attribute: if exists, ignore the click.
This will not change the UI of the element, just ignore repetative clicks.
Rough example using pure JavaScript (as you didn't tag your question with jQuery) is available here: http://jsfiddle.net/248g8/
If this is a big concern for you (and if the obvious answer of "make sure your server always responds really fast" isn't possible ;-) I would suggest a modified version of your (2) is the way forward.
The critical thing here is to give the user sufficient feedback that they feel that something is happening - ideally without blocking off the possibility of the user clicking again in those few cases where something genuinely has gone wrong.
Using javascript to make a small swirly "loading..." graphic may be effective here - and it's easy to set this up so that browsers that don't support javascript (or have it disabled) fall back to the standard link behaviour. Though I would only do this for forms where there is an expectation of taking a long time (or where this might scare the user) - it will make the site rather distracting to use, and in any case (a) users are used to links occasionally being slow on the internet, and (b) your server should be powerful enough to cope with the occasional extra hit :-)
You can disable the link or submit button - but this is frustrating for the user in the case where the submission fails for some reason (my bank does this, and TBH it scares me that they don't realise they should instead "program round" the double-submit issue as you described it!).
I certainly wouldn't disable the link and then re-enable it after a timeout - this would be very confusing for the user...
If you're using jQuery, then maybe you can listen for double clicks across the <BODY> tag and then prevent propagation.
$("body").live('dblClick',function()
{
return false;
});
I would say either:
Just leave it. As long as you've programmed against double-submissions on forms, who cares about a few extra processes?
Disable the link for a few seconds, as you've suggested. That was my first thought before I got to that part of your question. With jQuery (alter for your library of choice):
$('a').live('click',function()
{
var returnFalse = function () { return false; };
$(this).click(returnFalse);
window.setTimeout(function () { $(this).unbind('click',returnFalse) }, 3000);
}
I have an interactive html5 canvas thing where sometimes users will want to undo their actions. I have the logic for doing that implemented, but I'm not sure of how to properly catch the "user wants to undo" event.
Currently, I just listen to keyboard events and interpret "CTRL+Z" as a request-to-undo, like this:
document.addEventListener("keydown", e => {
const Z_KEY = 90;
let isUndo = e.keyCode == Z_KEY && e.ctrlKey && !e.shiftKey;
if (isUndo) {
restore(revision.undo());
}
});
The problem is that the standard shortcut for undo-ing varies by OS, and there are totally orthogonal ways to trigger it (such as shaking your phone).
What I want is to somehow tell the browser that I'm supporting undo, and that it should forward all the crazy OS-specific ways of triggering undo to a method I specify. As things stand now, the browser has no idea the user is doing anything that would involve undo-ing. All the browser sees is a canvas being clicked on and drawn to.
Is there a standard way to ask the browser to catch all the undo events for me? In a future-proof way that keeps working even as vendors invent new undo actions? What about a hacky workaround? Or perhaps there's a library whose focus is to solve this particular problem?
Notes:
This question differs from How to handle undo/redo event in javascript?. That one is asking about catching changes to an element, whereas I always know about any changes because my code is the one performing those changes.
The question Listen to undo/redo event in contenteditable div is also about change-detection instead of implementing undo, and is limited to a particular type of element. I'm willing to use custom elements to make this work.
There's no standard javascript way of hooking things like undo/redo as there is no specific event for them.
Maybe Mousetrap does what you want. It's a library for abstracting keyboard events in javascript and includes a way to do a generic [system modifier]+key hotkey kind of thing.
That said, you'll probably need a button somewhere if you want mobile. (I'm not familiar with the shake-to-undo action. That seems like new age hippy nonsense. =P )