我的問題是我有一個類似於Stack Overflow的投票系統。我的問題是,一個人可以垃圾郵件的投票按鈕,這使得小故障,並提交更多的時間比它應該。例如,如果某個帖子上有10張投票,我可以反覆點擊投票向上按鈕,它將增加兩張或三張選票而不是一張。同樣,我可以用向下按鈕來做到這一點。我如何防止這種情況?如何防止垃圾郵件發送ajax表格
的index.php:
<?php
session_start();
require('db.php');
$pid = 2;
$uid = $_SESSION['id'];
$sql = mysqli_query($con, "SELECT * FROM posts WHERE pid = '$pid'"); //check to see how many likes the post has
$r = mysqli_fetch_assoc($sql);
$body = $r['body'];
$likes = $r['likes'];
$sql2 = mysqli_query($con, "SELECT * FROM likes WHERE pid = '$pid' AND uid = '$uid'"); //check to see if user has voted
$n = mysqli_num_rows($sql2);
if ($n == 0) {
//user hasn't liked or down vote anything yet
$liked = "no";
} else {
if ($n > 1) {
//like scammed
echo "<script>alert('Stop spamming for votes. You are banned for spam.')</script>";
exit("You have been banned for spam");
//This isn't fool proof though, and I don't want to ban people for this. It would be best if I could just prevent the vote scam in the first place
}
$r = mysqli_fetch_assoc($sql2);
$type = $r['like_type'];
if ($type == '0') {
$liked = "liked";
} else {
$liked = "disliked";
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<script src="//code.jquery.com/jquery-latest.min.js"></script>
<style>
.selected {
color: red;
}
</style>
</head>
<body>
<div class="post">
<p><?php echo $body; ?></p>
</div>
<div class="likes">
<a href="javascript:;" class="upvote <?php if ($liked == 'liked') {echo "selected";} ?>" id='up-<?php echo $pid; ?>' onclick="vote('up', '<?php echo $pid; ?>', '<?php echo $uid; ?>', 'up-<?php echo $pid; ?>', 'votes-<?php echo $pid; ?>')">Upvote</a>
<span id="votes-<?php echo $pid; ?>"><?php echo $likes; ?></span>
<a href="javascript:;" class="downvote <?php if ($liked == 'disliked') {echo "selected";} ?>" id='down-<?php echo $pid; ?>' onclick="vote('down', '<?php echo $pid; ?>', '<?php echo $uid; ?>', 'down-<?php echo $pid; ?>', 'votes-<?php echo $pid; ?>')">Downvote</a>
</div>
</body>
的Javascript票()函數
function vote(type, pid, uid, id, voteId) {
var vote = $('#'+ id);
if (vote.hasClass('selected')) {
//user voted for this
$.post("vote.php", {pid: pid, uid: uid, type: type, vote: 'reset'}, function(d) {
if (d == '0' || d == '1') {
vote.removeClass('selected');
var votes = $('#' + voteId);
var num = votes.text();
if (d == '1') {
votes.text(++num);
} else {
votes.text(--num);
}
} else {
alert('An error occurred')
}
});
} else {
var upVoteId = $('#up-' + pid);
var downVoteId = $('#down-' + pid);
if (upVoteId.hasClass('selected') || downVoteId.hasClass('selected')) {
//user wants to switch votes
$.post('vote.php', {pid: pid, uid: uid, type: type, vote: 'switch'}, function(data) {
var votes = $('#' + voteId);
var num = votes.text();
if (data == '1') {
//downvote successful
votes.text(parseInt(num) - 2);
vote.addClass('selected');
upVoteId.removeClass('selected');
}
if (data == '0') {
//upvote successful
votes.text(parseInt(num) + 2);
vote.addClass('selected');
downVoteId.removeClass('selected');
}
if (d == 'error') {
alert('error');
}
});
} else {
$.post('test2.php', {type: type, pid: pid, uid: uid}, function(d) {
if (d == "1") {
//everything good
$('#' + type + '-<?php echo $pid; ?>').addClass('selected');
var votes = $("#" + voteId).text();
if (type == 'down') {
//downvote
votes = --votes;
$('#' + voteId).text(votes);
} else {
votes = ++votes;
$('#' + voteId).text(votes);
}
} else {
alert('failed');
}
});
}
}
}
}
Vote.php
<?php
session_start();
require('db.php');
if (!isset($_SESSION['id'], $_SESSION['un'])) {
//not logged in
header('Location: index.php');
exit;
} else {
if (!isset($_POST['uid'], $_POST['pid'], $_POST['type'], $_POST['vote'])) {
//form not submitted
header('Location: home.php');
exit;
} else {
$uid = (int)$_SESSION['id'];
$pid = (int)$_POST['pid'];
$type = preg_replace('#[^a-z]#', '', $_POST['type']);
$vote = preg_replace('#[^a-z]#', '',$_POST['vote']); //vote type
if ($vote == 'reset') {
//initiate vote reset
if ($type == 'down') {
//downvote
$sql = mysqli_query($con, "DELETE FROM likes WHERE like_type = '1' AND pid = '$pid' AND uid = '$uid'"); //delete the downvote
$sql2 = mysqli_query($con, "UPDATE posts SET likes = likes + 1 WHERE pid = '$pid'");
if ($sql) {
echo "1"; // 1
exit;
} else {
echo "error";
exit;
}
} else {
//upvote
$sql = mysqli_query($con, "DELETE FROM likes WHERE like_type = '0' AND pid = '$pid' AND uid = '$uid'"); //delete upvote
$sql2 = mysqli_query($con, "UPDATE posts SET likes = likes - 1 WHERE pid = '$pid'");
if ($sql) {
echo "0"; // 0
exit;
} else {
echo "error";
exit;
}
}
}
if ($vote == 'switch') {
//user wanted to switch vote
if ($type == 'down') {
//user had voted up but wants to vote down now
$sql = mysqli_query($con, "DELETE FROM likes WHERE like_type = '0' AND pid = '$pid' AND uid = '$uid'"); //delete the previous vote
$sql2 = mysqli_query($con, "INSERT INTO likes (pid, uid, like_type, date_liked) VALUES ('$pid', '$uid', '1', now())"); //insert new vote
$sql3 = mysqli_query($con, "UPDATE posts SET likes = likes - 2 WHERE pid = '$pid'");
if ($sql AND $sql2 AND $sql3) {
//all three queries were successful
echo "1";
exit;
} else {
echo "error";
exit;
}
} else {
//user had voted down but wants to vote up now
$sql = mysqli_query($con, "DELETE FROM likes WHERE like_type = '1' AND pid = '$pid' AND uid = '$uid'") or die(mysqli_error($con)); //delete the previous vote
$sql2 = mysqli_query($con, "INSERT INTO likes (pid, uid, like_type, date_liked) VALUES ('$pid', '$uid', '0', now())"); //insert new vote
$sql3 = mysqli_query($con, "UPDATE posts SET likes = likes + 2 WHERE pid = '$pid'");
if ($sql AND $sql2 AND $sql3) {
//all three queries were successful
echo "0";
exit;
} else {
echo "error";
exit;
}
}
}
}
}
Test2.php
<?php
require('db.php');
$pid = $_POST['pid'];
$uid = $_POST['uid'];
$type = $_POST['type'];
if ($type == "down") {
//downvote
$type = 1;
$sql = mysqli_query($con, "INSERT INTO likes (uid, pid, like_type, date_liked) VALUES ('$uid', '$pid', '$type', now())");
$sql2 = mysqli_query($con, "UPDATE posts SET likes = likes - 1 WHERE pid = '$pid'");
if ($sql) {
echo '1';
exit;
}
} else {
//upvote
$type = 0;
$sql = mysqli_query($con, "INSERT INTO likes (uid, pid, like_type, date_liked) VALUES ('$uid', '$pid', '$type', now())");
$sql2 = mysqli_query($con, "UPDATE posts SET likes = likes + 1 WHERE pid = '$pid'");
if ($sql) {
echo '1';
exit;
}
}
這些是我目前使用的頁面。我計劃將test2.php
移動到vote.php
。
在我的數據庫中,我有兩張表,一張存儲所有帖子的詳細信息,包括投票數。第二張表是存儲誰投了哪個帖子,以及是否投票或停止投票。
如果我可以讓我的系統更高效,請給我提示或建議。
很多方法可以做到這一點,一個快速的發送的投票數與請求。忽略來自同一會話的任何數字。 –
一種方法是統計嘗試次數,然後簡單地禁用該帖子。 – Jonast92