За последние 24 часа нас посетили 20167 программистов и 1081 робот. Сейчас ищут 756 программистов ...

Помогите разобраться с сессиями или куками.

Тема в разделе "PHP для новичков", создана пользователем kvadim, 28 июн 2016.

  1. kvadim

    kvadim Активный пользователь

    С нами с:
    1 сен 2015
    Сообщения:
    69
    Симпатии:
    0
    Здравствуйте, делаю страничку голосования. Сложность заключается в том, что ни как не могу понять, как сделать запрет на повторное голосование. По ip запрет работает, это если за один и тот же пункт, голосовать в тот же день, не получится, а вот в тот же день но за второй пункт, голосование происходит. Я где-то читал, что такое можно сделать используя сессию или куки, но что-то я их не могу победить. :(
     
  2. Ganzal

    Ganzal Суперстар
    Команда форума Модератор

    С нами с:
    15 мар 2007
    Сообщения:
    9.902
    Симпатии:
    969
    Показывай как делаешь
     
  3. kvadim

    kvadim Активный пользователь

    С нами с:
    1 сен 2015
    Сообщения:
    69
    Симпатии:
    0
    Код (Text):
    1. <?php
    2. include("config.php");
    3.  
    4. $teacher_id = $_POST["teacher"];
    5. $teacher_id = strip_tags($teacher_id);
    6. $teacher_id = mysqli_real_escape_string($link, $teacher_id);
    7. $teacher_id = trim($teacher_id);
    8.  
    9. $ip_address = $_SERVER["REMOTE_ADDR"];
    10. $ip_address = strip_tags($ip_address);
    11. $ip_address = mysqli_real_escape_string($link, $ip_address);
    12. $ip_address = trim($ip_address);
    13.  
    14. $data = date("Ymd");
    15. $data = strip_tags($data);
    16. $data = mysqli_real_escape_string($link, $data);
    17. $data = trim($data);
    18.  
    19.  
    20. $sql = "SELECT * FROM teachers WHERE id='".$teacher_id."'";
    21.  
    22. if($result = mysqli_query($link, $sql))
    23. {
    24.     if(!$result)
    25.     {
    26.     echo "Запись пуста".mysqli_error();
    27.     }
    28.     else
    29.     {
    30.     $row = mysqli_fetch_assoc($result);
    31.     //var_dump($row);
    32.  
    33.     if($row['data'] == $data || $row['ip_address'] == $ip_address)
    34.     {
    35.         include("ok.php");
    36.     }
    37.     else
    38.     {
    39.         $new_vote = $row["vote"] + 1;
    40.         $sql = "UPDATE teachers SET vote='".$new_vote."', data='".$data."', ip_address='".$ip_address."' WHERE id='".$teacher_id."'";
    41.         $result = mysqli_query($link, $sql);
    42.         if(!$result)
    43.         {
    44.         echo "Запись не произошла ".mysqli_error();
    45.         }
    46.         else
    47.         {
    48.         include("ok2.php");
    49.         }
    50.     }
    51.     }
    52. }
    53. ?>
     
  4. Ganzal

    Ganzal Суперстар
    Команда форума Модератор

    С нами с:
    15 мар 2007
    Сообщения:
    9.902
    Симпатии:
    969
    Если у учителя айдишник - цифра, то достаточно кастовать тип переменной вместо вот этого полового извращения с обрезанием и экранированием.
    Данные, которые ты генерируешь внутри скрипта иногда могут не представлять угрозы, в отличии от присылаемых пользователем. Вот это извращение с обрезанием и экранированием даты - лишнее.
    Для компактного хранения айпишника его можно конвертировать в число из четырех байт. Потому что айпишник это число из четырех байт. Просто для удобочтения его записывают отдельными октетами.

    Защиты собственно тут не особо видно. Расскажи задумку-то.
     
  5. kvadim

    kvadim Активный пользователь

    С нами с:
    1 сен 2015
    Сообщения:
    69
    Симпатии:
    0
    Айдишник учителя цифра, а как конвертировать айпи? И тогда вопрос, как тогда сделать, запрет на голосование, не только по айпи, но и чтобы пользователь мог голосовать, всего лишь один раз в сутки, не зависимо от количества предлогаемых пуктов голосования. Потому как на данный момент, запрет работает, только по айпи, и только для конкретно выбранного айдишника учителя. Но таких айдишников около 30, как запретить, пользователю голосовать за все остальные оставшиеся. Не знаю понятно ли я выражаюсь...
     
  6. askanim

    askanim Старожил

    С нами с:
    7 апр 2016
    Сообщения:
    2.201
    Симпатии:
    166
    Адрес:
    GABRIEL
    Берёшь при голосовании, когда ты пишешь обработчик его

    типа вот такого-во вида.

    PHP:
    1. if(isset($_POST['submit'])) {
    2.       session_start() ;
    3.       if(!empty($_SESSION['session'])) {
    4.      echo 'Пошёл нахер отседа ты уже голосовал!';
    5. }
    6. else {
    7.       /// Тут делаешь что тебе надо и в конце
    8.         Присваиваешь сессию
    9.         $_SESSION['session'] = 1;
    10.        
    11.  
    12. }
    13.  
    14.  
    15.  
    16. }
    Только почитай про сессии, как например увеличть жизнь сессии, и как сделать чтобы сессия не закрывалась когда браузер закрываешь.

    А можно это всё сделать ещё в бд. Например создать колонку, имя id пользователя, и колонку проголосова. в boolen

    1 значит да, и 0 значит нет.
    При голосовании ставишь её в 1 и при повторном голосовании проверяешь, в базу у этого пользователя, там 1 или 0 если 1 значит голосовал. Если 0 значит ещё не голосовал. Если голосование доступно в течении суток, можешь поставить планировщик задач на очистку таблицы, но надо тебе про cron почитать. На самом деле не чего в этой задаче сложного нет, просто у тебя не хватает знаний, кстате такую задачу наверно лучше не через сессии реализовывать. а через базу всё таки, я бы наверно через базу решил этот вопрос. Хотя можешь ещё куками, но куки можно взять и поменять в браузере, в итоге смысл что ты будешь записывать в куки :D
     
  7. kvadim

    kvadim Активный пользователь

    С нами с:
    1 сен 2015
    Сообщения:
    69
    Симпатии:
    0
    Я где-то читал, что можно использовать такую вот функцию
    Код (Text):
    1. setcookie("done","yes",time()+1800);
    Но, как потом это значение впихнуть в переменную и записать ее в бд? Потому как у меня не получалось. И еще вопрос, для этого надо создавать отдельную таблицу или можно создать поле в таблице с учителями? Сейчас у меня всего две таблицы teachers, где хранятся ФИО учителей и названия их предметов, а вторая таблица type_teacher, там хранятся данные к какой категории они принадлежат, но с этим проблем нет. там все нормально работает. Вот структура таблицы teachers
    Код (Text):
    1. CREATE TABLE IF NOT EXISTS `teachers` (
    2.   `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
    3.   `name_teachers` text NOT NULL,
    4.   `title_themes` text NOT NULL,
    5.   `vote` int(11) NOT NULL DEFAULT '0',
    6.   `data` date NOT NULL,
    7.   `ip_address` varchar(15) NOT NULL,
    8.   `id_type` int(11) NOT NULL,
    9.   `session_id` varchar(255) NOT NULL,
    10.   PRIMARY KEY (`id`)
    11. ) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=39 ;
     
  8. Ganzal

    Ganzal Суперстар
    Команда форума Модератор

    С нами с:
    15 мар 2007
    Сообщения:
    9.902
    Симпатии:
    969
    А кто голосует? Анонимы или зарегистрированные пользователи?
     
  9. denis01

    denis01 Суперстар
    Команда форума Модератор

    С нами с:
    9 дек 2014
    Сообщения:
    12.230
    Симпатии:
    1.715
    Адрес:
    Молдова, г.Кишинёв
    @kvadim тебе @askanim правильно про базу написал. В базе делаешь таблицу id, date, ip и перед тем как показать пользователю форму голосования и принять его голос, ты делаешь запрос в эту таблицу с его where ip = $ip and `date` = NOW() и если ты получил запись, значит пользователь голосовал. Если нет такой ещё записи то пусть голосует и после голосования создавай такую запись. Тут уникальная запись выйдет ip пользователя и дата голосования.
     
  10. kvadim

    kvadim Активный пользователь

    С нами с:
    1 сен 2015
    Сообщения:
    69
    Симпатии:
    0
    Анонимы
     
  11. Ganzal

    Ganzal Суперстар
    Команда форума Модератор

    С нами с:
    15 мар 2007
    Сообщения:
    9.902
    Симпатии:
    969
    Ну тогда делай как @denis01 сказал
     
  12. kvadim

    kvadim Активный пользователь

    С нами с:
    1 сен 2015
    Сообщения:
    69
    Симпатии:
    0
    Собственно у меня и так проверяется существует ли запись с определенным ip и датой, я ж код предоставил, там вроде бы понятно. Я же писал, что по айпи аноним не может больше одного раза в сутки проголосовать за один конкретный пункт. Проблема в том, что анониму предоставляется 30 пунктов, если он один раз проголосовал в день за 1 пункт, то как запретить ему голосовать и за второй пункт в тот же день.
    Подскажите, сколько тогда должно быть у меня таблиц?
     
    #12 kvadim, 29 июн 2016
    Последнее редактирование: 29 июн 2016
  13. denis01

    denis01 Суперстар
    Команда форума Модератор

    С нами с:
    9 дек 2014
    Сообщения:
    12.230
    Симпатии:
    1.715
    Адрес:
    Молдова, г.Кишинёв
    Ты за любой пункт перед тем как разрешать голосовать смотри есть ли в базе ip и дата на сегодня, если есть то за любой пункт не давай голосовать
     
  14. kvadim

    kvadim Активный пользователь

    С нами с:
    1 сен 2015
    Сообщения:
    69
    Симпатии:
    0
    Вот просмотрите пожалуйста мой код который я писал выше, подскажите что в нем надо переделать, потому как я что-то не совсем понимаю...что именно надо там поменять
     
  15. denis01

    denis01 Суперстар
    Команда форума Модератор

    С нами с:
    9 дек 2014
    Сообщения:
    12.230
    Симпатии:
    1.715
    Адрес:
    Молдова, г.Кишинёв
    @kvadim там нету запроса в таблицу в которой храниться IP и дата когда голосовали. Перед голосованием надо проверить голосовал человек или нет при этом не учитывать пункт за который он голосовал, учитывать только IP и дату, и если такая запись найдётся, не давать ему голосовать.
     
  16. kvadim

    kvadim Активный пользователь

    С нами с:
    1 сен 2015
    Сообщения:
    69
    Симпатии:
    0
    Ну, как нет а это?
    Код (Text):
    1.  
    2. // тут меня берут данные из таблицы в которой хранятся не только ФИО, количество голосов за конкретного человека, а так же айпи и дата голосования
    3. $sql = "SELECT * FROM teachers WHERE id='".$teacher_id."'";
    4. if($result = mysqli_query($link, $sql))
    5. {
    6.     if(!$result)
    7.     {
    8.     echo "Запись пуста".mysqli_error();
    9.     }
    10.     else
    11.     {
    12.     $row = mysqli_fetch_assoc($result);
    13.     //var_dump($row);
    14.  
    15. /// тут у меня проверяется если человек голосовал, и если совпадают айпи и дата, то вывести сообщение о то, что уже голосовали, просто я это сообщение в отдельный файл запихнул ok.php
    16.  
    17.     if($row['data'] == $data || $row['ip_address'] == $ip_address)
    18.     {
    19.         include("ok.php");
    20.  
    21.     }
    22.     else
    23.     {
    24. // А тут если айпи и дата не совпадают, то обновлять данные
    25.         $new_vote = $row["vote"] + 1;
    26.         $sql = "UPDATE teachers SET vote='".$new_vote."', data='".$data."', ip_address='".$ip_address."' WHERE id='".$teacher_id."'";
    27.         $result = mysqli_query($link, $sql);
    28.         if(!$result)
    29.         {
    30.         echo "Запись не произошла ".mysqli_error();
    31.         }
    32.         else
    33.         {
    34.         include("ok2.php");
    35.         }
    36.     }
    37.     }
    38. }
    Что тогда в этом случае надо поменять?
     
  17. denis01

    denis01 Суперстар
    Команда форума Модератор

    С нами с:
    9 дек 2014
    Сообщения:
    12.230
    Симпатии:
    1.715
    Адрес:
    Молдова, г.Кишинёв
    покажи только запрос который проверяет ip и дату
     
  18. kvadim

    kvadim Активный пользователь

    С нами с:
    1 сен 2015
    Сообщения:
    69
    Симпатии:
    0
    Так вот же из общего запроса
    Код (Text):
    1. $sql = "SELECT * FROM teachers WHERE id='".$teacher_id."'";
    в этой таблице teachers хранятся и дата и айпи, а вот условие

    Код (Text):
    1. if($row['data'] == $data || $row['ip_address'] == $ip_address)

    которое проверяет данные взятые из бд и которые были получены в этих строках
    Код (Text):
    1.  
    2. //тут переменная $ip_address получает айпи из глобального массива $_SERVER["REMOTE_ADDR"];
    3. $ip_address = $_SERVER["REMOTE_ADDR"];
    4. $ip_address = strip_tags($ip_address);
    5. $ip_address = mysqli_real_escape_string($link, $ip_address);
    6. $ip_address = trim($ip_address);
    7.  
    8. //а тут получает переменная $data текущую новую дату
    9. $data = date("Ymd");
    10. $data = strip_tags($data);
    11. $data = mysqli_real_escape_string($link, $data);
    12. $data = trim($data);
     
  19. denis01

    denis01 Суперстар
    Команда форума Модератор

    С нами с:
    9 дек 2014
    Сообщения:
    12.230
    Симпатии:
    1.715
    Адрес:
    Молдова, г.Кишинёв
    где тут условие WHERE для IP and date? Я же об этом писал и давал псевдокод SQL выполнив который нужно проверить есть результат или нету
     
  20. kvadim

    kvadim Активный пользователь

    С нами с:
    1 сен 2015
    Сообщения:
    69
    Симпатии:
    0
    Так этого что не достаточно
    Код (Text):
    1. if($row['data'] == $data || $row['ip_address'] == $ip_address)
    ?
    Не ужели надо обязательно еще и в запрос это пропихивать? Что-то я вообще ничего не пойму. Вы можете хотя бы схематично показать, что надо поменять? Вернее даже не так, а что за чем должно идти. А то у меня уже каша в голове...Если конечно Вам не трудно.
     
  21. Ganzal

    Ganzal Суперстар
    Команда форума Модератор

    С нами с:
    15 мар 2007
    Сообщения:
    9.902
    Симпатии:
    969
    @kvadim у тебя запрос "выбрать всё где учитель такой-то" может вернуть не только одну строку, верно? ГОЛОСУЮЩИХ ЖЕ МНОГО. А ты потом проверяешь только первый кортеж в результирующей таблице. С какой вероятностью это будет запись именно этого голосующего? С маленькой. Поэтому тебе и говорят что нужно дергать строку по учитель-дата-айпишник. Тогда либо строка будет, либо её не будет. Одна или ноль. Понимаешь?
     
  22. kvadim

    kvadim Активный пользователь

    С нами с:
    1 сен 2015
    Сообщения:
    69
    Симпатии:
    0
    А тут тоже надо будет изменять условие или оставлять такое же?
    Код (Text):
    1. if($row['data'] == $data || $row['ip_address'] == $ip_address)
     
  23. Ganzal

    Ganzal Суперстар
    Команда форума Модератор

    С нами с:
    15 мар 2007
    Сообщения:
    9.902
    Симпатии:
    969
    А ты как сам думаешь? Ты спрашиваешь у СУБД "Дай мне строку где учитель такой-то, айпишник такой-то и дата такая-то". Она тебе отвечает нулем или одной строкой. Вот если там одна строка в ответе - нужно ли, мать её, на стороне пхп проверять на соответствие даты и айпишника? А УЧИТЕЛЯ ПОЧЕМУ ВДОГОНКУ НЕ ПРОВЕРИТЬ? Кол-во строк в результате достаточно. И выбирать можно псевдокортеж с 1.
     
  24. kvadim

    kvadim Активный пользователь

    С нами с:
    1 сен 2015
    Сообщения:
    69
    Симпатии:
    0
    Значит как я понимаю, запрос должен быть такой
    Код (Text):
    1. $sql = "SELECT * FROM teachers WHERE id='".$teacher_id."'AND ip_address="'.$ip_address.'" AND data="'.$data.'"  ";
    и условие проверки
    Код (Text):
    1. if($row['data'] == $data || $row['ip_address'] == $ip_address || $row['id'] == $teacher_id)
    , правильно ли я все понял? Если нет, то поправьте пожалуйста.
     
  25. Ganzal

    Ganzal Суперстар
    Команда форума Модератор

    С нами с:
    15 мар 2007
    Сообщения:
    9.902
    Симпатии:
    969
    С первым понял правильно. Только можно выбирать не * а 1. Тебе же не нужен кортеж. Тебе нужно только знать, есть ли он в базе.
    А вот со вторым понял не правильно. Нужно проверять только кол-во строк в результате запроса.