We have a setup where a custom module assigns roles via the API to site visitors based on IP address, but they do not log in to the site, so they are always anonymous. There are some differences in the pages they should see but AuthCache caches the same page for both anonymous roles. This affects 6.x and 7.x.

The problem, I am sure is in this function:

function _authcache_is_account_cacheable($account = false) {
  if (!$account) {
    global $user;
    $account = $user;
  }

  // Check if caching is enabled for user's role
  $cache_roles = variable_get('authcache_roles', array());

  // Anonymous
  if (!$account->uid && !in_array(DRUPAL_ANONYMOUS_RID, $cache_roles)) {
    return FALSE;
  }
  // Logged-in
  else if ($account->uid) {
    unset($cache_roles[DRUPAL_ANONYMOUS_RID]);
    $extra_roles = array_diff(array_keys($account->roles), $cache_roles);

    // Admin selected a role, but did not selected "authenticated user"
    if ($extra_roles[0] == DRUPAL_AUTHENTICATED_RID && count($extra_roles) == 1 && count($account->roles) > 1 ) {
      return TRUE;
    }

    if (!empty($extra_roles)) {
      return FALSE;
    }
  }

  return TRUE;
}

In particular, it is this:

// Anonymous
  if (!$account->uid && !in_array(DRUPAL_ANONYMOUS_RID, $cache_roles)) {
    return FALSE;
  }

I thought I'd roll a patch for this. Does anyone have any thoughts on it?

Comments

simg’s picture

Nice idea, but not correct :)

How authcache works is that when a user logs in, they get assigned an authcache cookie in this code:

authcache.module:

function authcache_user_login(&$edit, $account) {
  global $_authcache_is_cacheable;
  // Cookie expiration
  $expires = ini_get('session.cookie_lifetime');
  $expires = (!empty($expires) && is_numeric($expires) ? REQUEST_TIME + (int) $expires : 0);

  //TODO:d7 - does it make sense to disable caching for uid == 1 ?
  //$no_cache = (isset($account->uid) && ($account->uid == 1 || !isset($_COOKIE['has_js'])));
  $no_cache = !isset($_COOKIE['has_js']);
  if ($no_cache) {
    setcookie('nocache', 1, $expires, ini_get('session.cookie_path'), ini_get('session.cookie_domain'), ini_get('session.cookie_secure') == '1');
  }
  else {
    setcookie('authcache', _authcache_key($account), $expires, ini_get('session.cookie_path'), ini_get('session.cookie_domain'), ini_get('session.cookie_secure') == '1');
  } 

The authcache cookie is an md5 hash of the users roles, set by this code:

authcache.helpers.inc:

function _authcache_key($account) {
  if (!$account->uid) {
    
    return '';
  }
  
  $keys = implode('.', array_keys($account->roles));
  return substr(md5($keys . drupal_get_private_key()), 0, 6);
}

The authcache key is used as a prefix to the cache key so that each url can be cached separately for each combination of roles.

Some people (apparently) modify the _authcache_key function to change the way authcache associates roles with cache keys.

Hope that helps?

cilefen’s picture

I does help a bit. Actually I just tested a little more and if only a custom anonymous role that isn't "anonymous user" is selected in admin/settings/performance/authcache, then authcache does not cache, so I think it may be happening elsewhere. Thoughts?

simg’s picture

Category: bug » support

unless your user gets logged in, they won't get the authcache cookie, so authcache will serve them the same anonymous content

why not enable debug mode (and also monitor the cookies that are present), that will give you a better idea of what is going on.

also, assigning roles to "anonymous" users sounds dodgy. with authcache serving pages to authenticated users is as fast as serving them to anonymous users, so I can't really see why you would want to create "custom" anonymous users.

cilefen’s picture

Ok I will try that -- thank you for the quick replies. Also, yes the "anonymous" role custom module is dodgy, but I inherited it, and the organization seems to really like it for some reason. If it helps you to know, the module assigns roles by IP address so some nodes will be shown to the given role only, and that is why I need this to work.

simg’s picture

well, one thing you could try is setting the authcache cookie with different values for different "custom anonymous user roles". authcache should just pick up that cookie and work with it.

cilefen’s picture

That sounds like a good idea, except the anonymous ones never get a cookie because cookies are set with hook_user.

simg’s picture

so, set the cookie in your "custom anonymous user" module ...

simg’s picture

Status: Active » Closed (fixed)

you're welcome. don't mention it ...