title: PHP voting system - ensure a person can only vote once
body: <p>I am working on a voting system and I am stuck at making sure someone can only vote once.  I looked at storing IPs but I read that places like universities use few IPs so if one person votes, most of the university is locked out of voting.  Currently I use cookies, which is nice until people realize I am using cookies.  It then becomes easy for them to delete the cookie and vote again.  Is there any reliable way to store a user's vote and ensure that they cannot vote again?  This is my current voting script:</p>
  
  <pre><code>&lt;?php
  include("config.php");
  
  //Checks URL for any GET variables and removes them.
  $url = $_POST['url'];
  $arr = explode("?", $url, 2);
  $url = $arr[0];
  
  
  //Makes sure someone didn't just go to /vote.php.
  if (empty($_POST['url'])) {
      print '&lt;script&gt;window.location = "errorpage";&lt;/script&gt;';
  } else {
  
  //Gets unique ID number for specific match up.
  $idnumber = $_POST['id'];
  
  //Checks to see if there is a cookie by the name of the unique matchup ID.
  if (!empty($_COOKIE[$idnumber])) {
  
      //If voted, go back and display already voted error.    
      print '&lt;script&gt; window.location = "'.$url.'?error=voted";&lt;/script&gt;';
  
  } else {
  
      //If user doesn't have the cookie, then set it to expire in 1 year. 
      setcookie("$idnumber", "1", strtotime( '+1 year' ));
  
  //Sets variable for a_vote or b_vote.
  $voteRow = $_POST['hiddenvote'];
  
  //Array of allowed values for column name.
  $allowed = array("a_vote","b_vote");
  
  //If $voteRow is not a_vote or b_vote, then go to error page.
  if(!in_array($voteRow, $allowed)) {
      print '&lt;script&gt;window.location = "errorpage";&lt;/script&gt;';
  } else {
  
      //Gets current votes and adds one for new value. 
      foreach($db-&gt;query("SELECT $voteRow FROM votes WHERE matchup = '$idnumber'") as $row) {
                  $votes = $row[$voteRow];
               }  
  
               $newvotes = $votes + 1;
  
  //Update query to send new vote amount.
  $sql = "UPDATE `votes` SET $voteRow = :newvotes WHERE `matchup` = :id";
   $statement = $db-&gt;prepare($sql);
   $statement-&gt;bindValue(":newvotes", $newvotes);
   $statement-&gt;bindValue(":id", $idnumber);
   $count = $statement-&gt;execute();
   $db = null;
  
  //Go to vote success page.
  print '&lt;script type="text/javascript"&gt;window.location = "'.$url.'?vote=success";&lt;/script&gt;'; 
  }
  }
  }
  ?&gt;
  </code></pre>