问题
I have these like buttons in a JQuery/Django tutorial I wrote:
<td id="toggle_color_like_cell_{{ color.id }}" class="td__toggle_color_like_button" data-color_id="{{ color.id }}">
{% include "color_liker/color_like_link__html_snippet.txt" %}
</td>
where color_like_link__html_snippet.txt
is:
<button class="button_{% if not color.is_favorited %}un{% endif %}liked"
>{% if color.is_favorited %}Yes{% else %}No{% endif %}</button>
The following JQuery-JavaScript is the AJAX call to toggle the like button (which changes the text between "Yes" I like it and "No" I don't), and, since each click hits the database, it also prevents clicks that are too rapid/close together.
My question is how much "attack prevention" like this should be integrated on the client-side? I am guessing a true DDOS would easily get past any JavaScript protection, but a user could try to just click things rapidly, and that is arguably something worth protecting against.
Eliminating this protection would make the code significantly less complicated. I'm not sure what's best here.
/*
This file must be imported immediately-before the close-</body> tag,
and after JQuery is imported.
*/
/**
The number of milliseconds to ignore clicks on the *same* like
button, after a button *that was not ignored* was clicked. Used by
<link to processLike>
Equal to <code>500</code>.
The disabling and re-enabling is logged to the console.
*/
var MILLS_TO_IGNORE_LIKES = 500;
/**
Executes a like click. Triggered by clicks on the various yes/no
links.
The disabling and re-enabling is logged to the console.
See <link to MILLS_TO_IGNORE_LIKES>
*/
Continued: Processor function:
var processLike = function() {
//The click listener is no longer attached to THIS button
//In this scope, "this" is the button just clicked on.
//The "this" in processLikeInner is *not* the button just clicked on.
var $button_just_clicked_on = $(this);
//The value of the "data-color_id" attribute.
var color_id = $button_just_clicked_on.data('color_id');
var processLikeInner = function(data, textStatus_ignored, jqXHR_ignored) {
//alert("sf data='" + data + "', textStatus_ignored='" + textStatus_ignored + "', jqXHR_ignored='" + jqXHR_ignored + "', color_id='" + color_id + "'");
$('#toggle_color_like_cell_' + color_id).html(data);
//Attack prevention. Dont process requests too close together.
console.log('Like disabled for: ' + MILLS_TO_IGNORE_LIKES);
setTimeout(function() {
$button_just_clicked_on.one('click', processLike);
console.log('Like re-enabled for color_id ' + color_id + ' ');
}, MILLS_TO_IGNORE_LIKES);
}
var config = {
url: LIKE_URL_PRE_ID + color_id + '/',
dataType: 'html',
success: processLikeInner
};
$.ajax(config);
};
Continued: Main function:
/**
The Ajax "main" function. Attaches the listeners to the elements on
page load.
*/
$(document).ready(function() {
/*
There are many buttons having the class
td__toggle_color_like_button
This attaches a listener to *every one*. Calling this again
would attach a *second* listener to every button, meaning each
click would be processed twice.
When a button is clicked, the listener for that *single button*
is disabled. It's re-enabled in processLikeInner with
$button_just_clicked_on.one('click', processLike);
*/
$('.td__toggle_color_like_button').one('click', processLike);
});
回答1:
You cannot do security or attack prevention from client side script
But what you are trying to do ( again not a security measure ) is a lot simpler if you use a library, underscore.js has a pretty good set of functions built into it.
you can use debounce for what you are trying to accomplish
$('#mybtn').click(_.debounce(function(e){
//do stuff
},500));
The button will only execute the function 500 milliseconds after the last call to it, effectively limiting the call to once every 500 milliseconds at most...
This is not a security or a DDOS prevention measure you have to do that sort of stuff on the server
回答2:
Based on konkked's answer, this is what I came up with. Note that this only requires underscore-min.js
, not underscore-min.map
.
/**
The number of milliseconds to ignore clicks on the *same* like
button, after a button *that was not ignored* was clicked. Used by
`$(document).ready()`.
Equal to <code>500</code>.
The disabling and re-enabling is logged to the console.
*/
var MILLS_TO_IGNORE_LIKES = 500;
Continued: Processor function
/**
Executes a like click. Triggered by clicks on the various yes/no
links.
The disabling and re-enabling is logged to the console.
See <link to MILLS_TO_IGNORE_LIKES>
*/
var processLike = function() {
//In this scope, "this" is the button just clicked on.
//The "this" in processServerResponse is *not* the button just clicked
//on.
var $button_just_clicked_on = $(this);
//The value of the "data-color_id" attribute.
var color_id = $button_just_clicked_on.data('color_id');
var processServerResponse = function(sersverResponse_data, textStatus_ignored,
jqXHR_ignored) {
//alert("sf sersverResponse_data='" + sersverResponse_data + "', textStatus_ignored='" + textStatus_ignored + "', jqXHR_ignored='" + jqXHR_ignored + "', color_id='" + color_id + "'");
$('#toggle_color_like_cell_' + color_id).html(sersverResponse_data);
}
var config = {
url: LIKE_URL_PRE_ID + color_id + '/',
dataType: 'html',
success: processServerResponse
//Should probably include a "fail" call, too.
};
$.ajax(config);
};
Continued: Main function:
/**
The Ajax "main" function. Attaches the listeners to the elements on
page load.
*/
$(document).ready(function() {
/*
There are many buttons having the class
td__toggle_color_like_button
This attaches a listener to *every one*. Calling this again
would attach a *second* listener to every button, meaning each
click would be processed twice.
---
Warning: Placing the true parameter outside of the debounce call:
$('#color_search_text').keyup(_.debounce(processSearch,
MILLS_TO_IGNORE_SEARCH), true);
results in "TypeError: e.handler.apply is not a function"
- https://stackoverflow.com/questions/24283006/e-handler-apply-is-not-a-function-in-jquery-table-sorter
- https://stackoverflow.com/questions/22588794/firefox-only-error-with-jquery-handleobj-handler-apply-is-not-a-function
*/
// API: http://jashkenas.github.io/underscore/#debounce
$('.td__toggle_color_like_button').click(_.debounce(processLike,
MILLS_TO_IGNORE_LIKES, true));
});
来源:https://stackoverflow.com/questions/28309850/how-much-prevention-of-rapid-fire-form-submissions-should-be-on-the-client-side