5

I want a node to be reached only by its alias but not its internal path. The reason behind this is that I will create a node type, allow anon users to create such nodes, but the alias will contain a random text, so that only the user with the actual url information can revisit this page. Example: www.example.com/node/9 -> only accessible by admin www.example.com/34h356hrgc35yh4geg -> only accessible to anon users with this information.

If an anon user tries www.example.com/node/9, they should see Forbidden error or Not Found.

3
  • 1
    Not in Drupal, but you can restrict it using Apache config. You can set up Apache so that some urls (in this case it would be those beginning /node ) require http authentication. This would be another layer on top of Drupal authentication, so it does add complexity but I don't see how else it could be achieved. See this question for details and good answers: stackoverflow.com/questions/23469351/…
    – naomi
    Aug 21 '17 at 15:09
  • Thank you. The problem with this approach for me is every node type's internal path is blocked. I would want only one node type's urls. Aug 22 '17 at 6:08
  • You would have to use aliases for all nodes.The pathauto module is great for that. However, 4k4's answer below looks better.
    – naomi
    Aug 22 '17 at 12:04
4

You can do this if speed is important in a middleware, checking if the request has no session and then block right away or in a request event subscriber after authentication checking for the path. Or a bit slower after routing if you want to include if the route matched is the canonical node route and use the node entity in your logic.

The easist but slowest is in a page preprocess hook. You can even do this in a theme. The cached page is varied by path and user permission by default and so the not found exception:

function mytheme_preprocess_page(&$variables) {
  if (\Drupal::currentUser()->isAnonymous()) {
    if (isset($variables['node'])) {
      $node = $variables['node'];
      if ($node instanceof \Drupal\node\NodeInterface) {
        if ($node->getType() == 'article') {
          $path = \Drupal::request()->getRequestUri();
          if (preg_match('#/node/\d+/*$#', $path)) {
            throw new \Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
          }
        }
      }
    }
  }
}

Because the 404 response is cached by the page cache the performance should be OK for most cases.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.