Correct IP with reverse proxy

Created on 30 January 2013, over 12 years ago
Updated 2 December 2024, 10 months ago

If you are running a reverse proxy in front of your webserver, then the module will store the proxy's IP address instead of the visitors'. This results in users not being able to vote because it looks like they already have.

🐛 Bug report
Status

Needs review

Version

1.6

Component

Code

Created by

🇺🇸United States murat_halici

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • Here’s a version of @dmegatool and @sazcurrain’s code which works with Drupal 10 (and probably 8+). I used Claude to write it but it’s working fine on an actual project. The full module code, with comments, is at GitHub.

    use Drupal\Core\Form\FormStateInterface;
    use Drupal\votingapi\VoteInterface;
    use Drupal\Core\Entity\EntityInterface;
    
    function cookie_voter_get_id() {
      $cookie_name = 'Drupal_CookieVoter';
    
      if (empty($_COOKIE[$cookie_name])) {
        $unique_id = uniqid('vote_', true);
        setcookie(
          $cookie_name,
          $unique_id,
          time() + 31536000, // 1 year expiration
          '/'
        );
        $_COOKIE[$cookie_name] = $unique_id;
      }
    
      return $_COOKIE[$cookie_name];
    }
    
    function cookie_voter_entity_create(EntityInterface $entity) {
      if ($entity instanceof VoteInterface && !\Drupal::currentUser()->id()) {
        $cookie_id = cookie_voter_get_id();
        $entity->set('vote_source', $cookie_id);
      }
    }
    
    function cookie_voter_rate_vote_data_alter(&$vote_data, $entity_type, $entity_bundle, $entity_id, $rate_widget, $settings, $user_id) {
      if (empty($user_id) || $user_id == 0) {
        $cookie_id = cookie_voter_get_id();
        $vote_data['vote_source'] = $cookie_id;
      }
    }
    
    function cookie_voter_entity_presave(EntityInterface $entity) {
      if ($entity instanceof VoteInterface && $entity->getOwnerId() == 0) {
        $cookie_id = cookie_voter_get_id();
        $entity->set('vote_source', $cookie_id);
      }
    }
    
    function cookie_voter_query_votingapi_vote_check_alter($query) {
      foreach ($query->conditions() as $key => $condition) {
        if (isset($condition['field']) &&
            $condition['field'] === 'vote_source' &&
            !\Drupal::currentUser()->id()) {
          $cookie_id = cookie_voter_get_id();
          $condition['value'] = $cookie_id;
          $query->condition('vote_source', $cookie_id, '=');
        }
      }
    }
    
    function cookie_voter_module_implements_alter(&$implementations, $hook) {
      if (in_array($hook, ['entity_create', 'rate_vote_data_alter'])) {
        if (isset($implementations['cookie_voter'])) {
          $group = $implementations['cookie_voter'];
          unset($implementations['cookie_voter']);
          $implementations = ['cookie_voter' => $group] + $implementations;
        }
      }
    }
    
  • Here’s a version of @dmegatool and @sazcurrain’s solution which works with Drupal 10 (and probably 8+). I used Claude to write it but it’s working fine on an actual project. The full module code with comments is at GitHub.

    use Drupal\Core\Form\FormStateInterface;
    use Drupal\votingapi\VoteInterface;
    use Drupal\Core\Entity\EntityInterface;
    
    function cookie_voter_get_id() {
      $cookie_name = 'Drupal_CookieVoter';
    
      if (empty($_COOKIE[$cookie_name])) {
        $unique_id = uniqid('vote_', true);
        setcookie(
          $cookie_name,
          $unique_id,
          time() + 31536000, // 1 year expiration
          '/'
        );
        $_COOKIE[$cookie_name] = $unique_id;
      }
    
      return $_COOKIE[$cookie_name];
    }
    
    function cookie_voter_entity_create(EntityInterface $entity) {
      if ($entity instanceof VoteInterface && !\Drupal::currentUser()->id()) {
        $cookie_id = cookie_voter_get_id();
        $entity->set('vote_source', $cookie_id);
      }
    }
    
    function cookie_voter_rate_vote_data_alter(&$vote_data, $entity_type, $entity_bundle, $entity_id, $rate_widget, $settings, $user_id) {
      if (empty($user_id) || $user_id == 0) {
        $cookie_id = cookie_voter_get_id();
        $vote_data['vote_source'] = $cookie_id;
      }
    }
    
    function cookie_voter_entity_presave(EntityInterface $entity) {
      if ($entity instanceof VoteInterface && $entity->getOwnerId() == 0) {
        $cookie_id = cookie_voter_get_id();
        $entity->set('vote_source', $cookie_id);
      }
    }
    
    function cookie_voter_query_votingapi_vote_check_alter($query) {
      foreach ($query->conditions() as $key => $condition) {
        if (isset($condition['field']) &&
            $condition['field'] === 'vote_source' &&
            !\Drupal::currentUser()->id()) {
          $cookie_id = cookie_voter_get_id();
          $condition['value'] = $cookie_id;
          $query->condition('vote_source', $cookie_id, '=');
        }
      }
    }
    
    function cookie_voter_module_implements_alter(&$implementations, $hook) {
      if (in_array($hook, ['entity_create', 'rate_vote_data_alter'])) {
        if (isset($implementations['cookie_voter'])) {
          $group = $implementations['cookie_voter'];
          unset($implementations['cookie_voter']);
          $implementations = ['cookie_voter' => $group] + $implementations;
        }
      }
    }
    
  • Status changed to Closed: outdated 25 days ago
Production build 0.71.5 2024