Disallow node discovery by ID

Jun 15 2009

Recently I wondered if viewing a node via its internal path could be disallowed, making it accessible using a path alias only. With hook_menu_alter(), a router item's page callback can be changed to our own function that will check if the requested path is internal or not.

<?php
function hidenid_menu_alter(&$items) {
 
$items['node']['page callback'] = 'hidenid_check';
 
$items['node/%node']['page callback'] = 'hidenid_check';
 
$items['node/%node/view']['page callback'] = 'hidenid_check';
}

function hidenid_check($node = NULL, $cid = NULL) {
 
$path = $_REQUEST['q'];
 
  if (
strpos($path, 'node') === 0) {
   
drupal_not_found();
    return;
  }
  return
node_page_view($node, $cid);
}
?>

You might be asking what's the point of this? Good question! I wondered how such a thing could be accomplished after dreaming up a schedule service built on Drupal. I didn't want to use a node access control, just restrict visibility with obfuscated URLs. Without such a solution a curious visitor could still view posts at node/NID. The above solution is a proof-of-concept, I haven't deployed beyond a prototype so there are likely to be implications I don't know about.

We can't use the PHP superglobal $_GET because Drupal overwrites 'q' in drupal_init_path(). In the above code example the $node argument defaults as NULL in hidenid_check() for the case the requested path is 'node', because no page arguments are set for that callback.

Of course, for practicality there must be an alias or the node cannot be viewed. That's where the core path module and Pathauto helps, perhaps altering the node form to require the alias field as well. And you could always allow user 1 or certain roles to view it via the internal path.

Comments

deviantintegral writes:

You might be interested in the URL Access which I wrote a while back. It lets you block access to a node unless you're using a specific UUID to access it. The site ended up not needing the feature, so I didn't develop it further.

Ben Jeavons writes:

Oh cool! When I searched for if this had been done before I don't recall seeing URL Access but thanks for sharing. I was going to say that hook_init() doesn't run for cached pages but that's only for 6. It's been too long since I've looked at 5.

Post new comment

The content of this field is kept private and will not be shown publicly.