After some trial and error an researching and researching I found out how to get it done.
Case:
The aim is to avoid that any other user than the admin can access administration pages starting with path "/admin/config/*". The point is that we have a administrator role in our project who should have access to the menu administration pages (they need the permission "Use the administration pages and help" to get to this administration page). With this permission they also see the "Configuration" menu item in toolbar and all sub menu items like "System" but these pages are empty.
How to achive that by altering the access checks
First define your own RouteSubscribe class in folder/file your_module/src/Routing/AdminRouteSubscriber.php:
namespace Drupal\your_module\Routing;
use Drupal\Core\Routing\RouteSubscriberBase;
use Symfony\Component\Routing\RouteCollection;
class AdminRouteSubscriber extends RouteSubscriberBase {
/**
* {@inheritdoc}
*/
public function alterRoutes(RouteCollection $collection) {
$path = '/admin/config';
foreach ($collection->all() as $routename => $route) {
if (substr($route->getPath(), 0, 13) == $path) {
$route->setRequirement(
'_custom_access',
'\Drupal\your_module\AccessChecks\CustomAccessChecks::access'
);
}
}
}
}
What we did here is to check the path of every route and if it starts with "/admin/config" it gets added our custom AccessCheck class defining the method "admimAccess" to be called.
Than go ahead and define your own access check class in folder/file your_module/src/AccessChecks/CustomAccessChecks.php:
namespace Drupal\your_module\AccessChecks;
use Drupal\Core\Routing\Access\AccessInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Access\AccessResultAllowed;
use Symfony\Component\Routing\Route;
use Drupal\Core\Routing\RouteMatchInterface;
class CustomAccessChecks implements AccessInterface {
/**
* A custom access check.
*
* @param \Drupal\Core\Session\AccountInterface $account
* Run access checks for this account.
*/
public function access(Route $route, RouteMatchInterface $route_match, AccountInterface $account) {
return AccessResultAllowed::allowedIf((int) $account->id() === 1);
}
}
This access method has to return an implementation of AccessResultInterface. We say that access is allowed if the current user has the id 1.
Lastly you need to add these classes to the service container by defining your your_module.services.yml in your module's root folder:
services:
your_module.route_subscriber:
class: Drupal\your_module\Routing\AdminRouteSubscriber
tags:
- { name: event_subscriber }
your_module.access_checker:
class: Drupal\your_module\AccessChecks\CustomAccessChecks
tags:
- { name: access_check }
After rebuilding your cache it works.