Skip to content

Commit

Permalink
IP cheat protection
Browse files Browse the repository at this point in the history
  • Loading branch information
itchief committed Nov 8, 2019
1 parent 656f36c commit e90903f
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 18 deletions.
2 changes: 2 additions & 0 deletions jquery-3.4.1.min.js

Large diffs are not rendered by default.

103 changes: 93 additions & 10 deletions process_star_rating.php
Original file line number Diff line number Diff line change
@@ -1,16 +1,36 @@
<?php

const
DSN = 'mysql:host=localhost;dbname=mydb',
DB_HOST = 'localhost',
DB_NAME = 'mydb',
DB_CHARSET = 'utf8',
DB_USER = 'root',
DB_PASSWORD = '';
DB_PASSWORD = '',
MAX_RATING = 5,
IS_CHECK_IP = true;

function log_write($message)
{
$log = date('d.m.Y H:i:s') . PHP_EOL . $message . PHP_EOL . '-------------------------' . PHP_EOL;
file_put_contents('error.log', $log, FILE_APPEND);
}

function getIp() {
$keys = [
'HTTP_CLIENT_IP',
'HTTP_X_FORWARDED_FOR',
'REMOTE_ADDR'
];
foreach ($keys as $key) {
if (!empty($_SERVER[$key])) {
$ip = trim(end(explode(',', $_SERVER[$key])));
if (filter_var($ip, FILTER_VALIDATE_IP)) {
return $ip;
}
}
}
}

if (empty($_SERVER['HTTP_X_REQUESTED_WITH']) || $_SERVER['HTTP_X_REQUESTED_WITH'] != 'XMLHttpRequest') {
exit(json_encode($output));
}
Expand All @@ -23,10 +43,18 @@ function log_write($message)

$count = 0;
$totalVotes = 1;
if (empty($_POST['id'])) {
log_write('Не передан id!');
exit(json_encode($output));
}
$ratingId = filter_var($_POST['id'], FILTER_SANITIZE_STRING);
if (strlen($ratingId) == 0) {
log_write('Параметр id имеет в качестве значения пустую строку!');
exit(json_encode($output));
}

try {
$conn = new PDO(DSN, DB_USER, DB_PASSWORD);
$conn = new PDO('mysql:host=' . DB_HOST . ';dbname=' . DB_NAME . ';charset=' . DB_CHARSET, DB_USER, DB_PASSWORD);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
log_write('Подключение не удалось: ' . $e->getMessage());
Expand All @@ -35,15 +63,12 @@ function log_write($message)

switch ($_POST['action']) {
case 'get_rating':
if (empty($_REQUEST['id'])) {
break;
}
$output['data'] = [
'rating_avg' => 0,
'total_votes' => 0
];
try {
$sql = 'SELECT rating_avg, total_votes FROM star_rating WHERE rating_id = :rating_id LIMIT 1';
$sql = 'SELECT id, rating_avg, total_votes FROM star_rating WHERE rating_id = :rating_id LIMIT 1';
$result = $conn->prepare($sql);
$data = ['rating_id' => $ratingId];
$result->execute($data);
Expand All @@ -53,6 +78,18 @@ function log_write($message)
'rating_avg' => $row['rating_avg'],
'total_votes' => $row['total_votes']
];
if (IS_CHECK_IP == true) {
$sql = 'SELECT count(*) FROM star_rating_ip WHERE rating_id = :rating_id AND rating_ip = :rating_ip';
$result = $conn->prepare($sql);
$data = ['rating_id' => $row[id], 'rating_ip' => getIp()];
$result->execute($data);
$countRows = $result->fetchColumn();
if ($countRows == 0) {
$output['data']['is_vote'] = false;
} else {
$output['data']['is_vote'] = true;
}
}
}
} catch (PDOException $e) {
log_write('Ошибка выборки данных: ' . $e->getMessage());
Expand All @@ -62,10 +99,16 @@ function log_write($message)
break;

case 'set_rating':
if (empty($_POST['id']) || empty($_POST['rating'])) {
if (empty($_POST['rating'])) {
log_write('Не получено значение рейтинга!');
break;
}
$id = 0;
$rating = (int)$_POST['rating'];
if ($rating < 1 || $rating > MAX_RATING) {
log_write('Полученное значение рейтинга ' . $rating . ' лежит вне допустимого диапазона!');
break;
}
$ratingAvg = $rating;
try {
$sql = 'SELECT id, rating_avg, total_votes FROM star_rating WHERE rating_id = :rating_id LIMIT 1';
Expand All @@ -75,6 +118,7 @@ function log_write($message)
$row = $result->fetch(PDO::FETCH_ASSOC);
if ($row) {
$count = 1;
$id = $row['id'];
$ratingAvg = $row['rating_avg'];
$totalVotes = $row['total_votes'];
}
Expand All @@ -83,17 +127,56 @@ function log_write($message)
break;
}

if ($count === 0) {
if ($count == 0) {
try {
$result = $conn->prepare('INSERT INTO star_rating (rating_id, rating_avg, total_votes) VALUES (:rating_id, :rating_avg, :total_votes)');
$result->execute(['rating_id' => $ratingId, 'rating_avg' => $ratingAvg, 'total_votes' => $totalVotes]);
if (IS_CHECK_IP == true) {
try {
$sql = 'SELECT id FROM star_rating WHERE rating_id = :rating_id LIMIT 1';
$result = $conn->prepare($sql);
$data = ['rating_id' => $ratingId];
$result->execute($data);
$row = $result->fetch(PDO::FETCH_ASSOC);
if ($row) {
try {
$result = $conn->prepare('INSERT INTO star_rating_ip (rating_id, rating_value, rating_ip) VALUES (:rating_id, :rating_value, :rating_ip)');
$result->execute(['rating_id' => $row['id'], 'rating_value' => $rating, 'rating_ip' => getIp()]);
} catch (PDOException $e) {
log_write('Ошибка добавления новой записи в таблицу star_rating_ip: ' . $e->getMessage());
break;
}
}
} catch (PDOException $e) {
log_write('Ошибка выборки данных: ' . $e->getMessage());
break;
}
}
} catch (PDOException $e) {
log_write('Ошибка добавления новой записи в базу: ' . $e->getMessage());
break;
}
} else {
$ratingAvg = ($ratingAvg * $totalVotes + $rating) / ($totalVotes + 1);
$totalVotes = $totalVotes + 1;
$totalVotes = $totalVotes + 1;
if (IS_CHECK_IP == true) {
$ip = getIp();
$sql = 'SELECT count(*) FROM star_rating_ip WHERE rating_id = :rating_id AND rating_ip = :rating_ip';
$result = $conn->prepare($sql);
$data = ['rating_id' => $id, 'rating_ip' => $ip];
$result->execute($data);
$countRows = $result->fetchColumn();
if ($countRows > 0) {
break;
}
try {
$result = $conn->prepare('INSERT INTO star_rating_ip (rating_id, rating_value, rating_ip) VALUES (:rating_id, :rating_value, :rating_ip)');
$result->execute(['rating_id' => $id, 'rating_value' => $rating, 'rating_ip' => $ip]);
} catch (PDOException $e) {
log_write('Ошибка добавления новой записи в таблицу star_rating_ip: ' . $e->getMessage());
break;
}
}
$sql = 'UPDATE star_rating SET rating_avg=:rating_avg, total_votes=:total_votes WHERE rating_id=:rating_id';
$data = [
'rating_id' => $ratingId,
Expand Down
24 changes: 16 additions & 8 deletions star_rating.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
$(function () {

var
processURL = '/process_star_rating.php',
output = [],
rating_star_class = '.star-rating_active .star-rating__item';

ratingStarClass = '.star-rating_active .star-rating__item';
if (localStorage.getItem('star_rating')) {
output = JSON.parse(localStorage.getItem('star_rating'));
}
$('.star-rating').each(function () {
var
_this = this,
ratingId = $(_this).attr('data-id');
if (output.indexOf(ratingId) < 0) {
$(_this).addClass('star-rating_active');
}
$.post('/process_star_rating.php', { 'action': 'get_rating', 'id': ratingId })
$.post(processURL, { 'action': 'get_rating', 'id': ratingId })
.done(function (data) {
if (data['result'] === 'success') {
var
Expand All @@ -23,6 +20,17 @@ $(function () {
$(_this).find('.star-rating__live').css('width', ratingAvg / 5 * 100 + '%');
$(_this).closest('.star-rating__wrapper').find('.star-rating__avg').text(ratingAvg.toFixed(1));
$(_this).closest('.star-rating__wrapper').find('.star-rating__votes').text('оценок: ' + totalVotes);
if (data['data']['is_vote'] !== undefined) {
if (data['data']['is_vote'] === false) {
if (output.indexOf(ratingId) < 0) {
$(_this).addClass('star-rating_active');
}
}
} else {
if (output.indexOf(ratingId) < 0) {
$(_this).addClass('star-rating_active');
}
}
}
});
});
Expand Down Expand Up @@ -55,13 +63,13 @@ $(function () {
$(this).closest('.star-rating__live').find('.star-rating__item').removeClass('star-rating__item_active');
});

$(document).on('click', rating_star_class, function (e) {
$(document).on('click', ratingStarClass, function (e) {
e.preventDefault();
var
_this = this,
ratingId = $(_this).closest('.star-rating').attr('data-id'),
rating = $(_this).attr('data-rating');
$.post('/process_star_rating.php', { 'action': 'set_rating', 'id': ratingId, 'rating': rating })
$.post(processURL, { 'action': 'set_rating', 'id': ratingId, 'rating': rating })
.done(function (data) {
if (!$.isEmptyObject(data)) {
if (data['result'] === 'success') {
Expand Down
11 changes: 11 additions & 0 deletions tables.sql
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,20 @@ CREATE TABLE `star_rating` (
`rating_avg` float NOT NULL,
`total_votes` int(10) UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `star_rating_ip` (
`id` int(10) UNSIGNED NOT NULL,
`rating_id` int(10) UNSIGNED NOT NULL,
`rating_value` tinyint(2) UNSIGNED NOT NULL,
`rating_ip` varchar(16) NOT NULL DEFAULT '0.0.0.0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `star_rating`
ADD PRIMARY KEY (`id`);
ALTER TABLE `star_rating_ip`
ADD PRIMARY KEY (`id`),
ADD KEY `rating_id` (`rating_id`);

ALTER TABLE `star_rating`
MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `star_rating_ip`
MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT;

0 comments on commit e90903f

Please sign in to comment.