跳转到主要内容
晨雨 提交于 27 August 2014

原文链接:https://www.drupal.org/node/2122195

最后更新于2014年6月12日。

使用permissions/roles简单检查

路由的数据结构允许你对访问的路由使用and/or关联角色来限定角色的访问权限。你可以结合这些权限检查方法使用access_mode选项来选择全部/部分权限。可以在路由结构中的requirements和options节查看。(The route data structure allows you to specify permissions and/or roles that are required to access the route. You can combine these access check methods with an any or all relation using the access_mode option. See the requirements and options section in the route structure.)

路由中自定义权限检查(Custom access checking on routes)

路由中的自定义访问检查 有时候,仅仅依靠权限add/or role是不够的,你需要做的自定义访问检查路由。为了实现这一目标,实现一个类accesscheckinterface用以检查访问。如果你的模块为Example,这是一个简单的实现例子。文件放置在

lib/Drupal/example/Access/CustomAccessCheck.php:
<?php
/**
 * @file
 * Contains \Drupal\example\Access\CustomAccessCheck.
 */
namespace Drupal\example\Access;
use Drupal\Core\Access\AccessCheckInterface;
use Drupal\Core\Session\AccountInterface;
use Symfony\Component\Routing\Route;
use Symfony\Component\HttpFoundation\Request;
/**
 * Checks access for displaying configuration translation page.
 */
class CustomAccessCheck implements AccessCheckInterface {
  /**
   * A user account to check access for.
   *
   * @var \Drupal\Core\Session\AccountInterface
   */
  protected $account;
  /**
   * Constructs a CustomAccessCheck object.
   *
   * @param \Drupal\Core\Session\AccountInterface
   *   The user account to check access for.
   */
  public function __construct(AccountInterface $account) {
    $this->account = $account;
  }
  /**
   * {@inheritdoc}
   */
  public function access(Route $route, Request $request) {
    // Check permissions and combine that with any custom access checking needed. Pass forward
    // parameters from the route and/or request as needed.
    return $this->account->hasPermission('do example things') && $this->someOtherCustomCondition();
  }
}
?>

额外的,如果需要添加一个访问类作为服务,那么需要在example.services.yml中添加一个入口(Additionally, you have to add the access class as a service by adding an entry in example.services.yml)

services:
  example.access_checker:
    class: Drupal\example\Access\CustomAccessCheck
    arguments: ['@current_user']
    tags:
      - { name: access_check, applies_to: _example_access_check }

通过添加’_example_access_check’标志到路由的requirements节里面,这个路由将会调用这权限检查(通过applies()方法里面匹配实现). 然后access()方法将会执行自定义的访问检查。也可以从第三方服务里面使用数据,按需要在任何时间完成需要的自定义的数据检查。(By adding the '_example_access_check' flag to the requirements section of a route, that route will have this access checker invoked (through the matching implemented in the applies() method). Then the access() method performs the custom access check. You can use data from third party services, custom data checking or even the time of day, as needed.)

There is of course no need to define a custom requirements flag for your access checker, if you can identify the right routes to work with without doing so.

简单的自定义权限检查器(Simplified custom access checker)

在一些情况下,如在单个路由入口中你需要添加一个访问权限检查器。

在这些情况下,你可以极大简化过程。

在这些情况你可以直接在路由定义中指定控制器,如下:

example:
  path: '/example'
  defaults:
    _controller: '\Drupal\example\Controller\ExampleController::content'
  requirements:
    _custom_access:  '\Drupal\example\Controller\ExampleController::access'
<?php
/**
 * @file
 * Contains \Drupal\example\Controller\ExamleController.
 */
namespace Drupal\example\Controller;
use Drupal\Core\Session\AccountInterface;
use Symfony\Component\HttpFoundation\Request;
/**
 * Builds an example page.
 */
class ExampleController {
  /**
   * A user account to check access for.
   *
   * @var \Drupal\Core\Session\AccountInterface
   */
  protected $account;
  /**
   * Constructs a CustomAccessCheck object.
   *
   * @param \Drupal\Core\Session\AccountInterface
   *   The user account to check access for.
   */
  public function __construct(AccountInterface $account) {
    $this->account = $account;
  }
  /**
   * Checks access for a specific request.
   *
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The request to check access for.
   */
  public function access(Request $request) {
    // Check permissions and combine that with any custom access checking needed. Pass forward
    // parameters from the route and/or request as needed.
    return $this->account->hasPermission('do example things') && $this->someOtherCustomCondition();
  }
}
?>

在这种情况下,access方法和类中的控制器相同,因此就没有必要增加一个独立的服务入口。(In this case, the access method is on the same class as the controller itself so there is no need for a separate service entry.)

在控制器内容方法里面的权限检查(Access checking in the controller content method)

因为一些原因如果你想控制器的内容方法中添加一些访问检查,你可以在路由定义中设置_access: true并且在控制器的内容方法作访问检查动作内容。如果你要使用这个方法,确保页面不正确或访问拒绝的时能返回合适的Symfony异常。这个获取内容由于上面的方法的解耦肯定优于混合页面逻辑访问。(Finally, if you need or want to do access checking in the controller content method for some reason, you can set _access: truein the route definition and do the access checking in the controller content method. If you take this approach, make sure to return the proper Symfony route exceptions if the page is not found or access should be denied. The above methods where access is decoupled from content are definitely preferred over mixing page logic with access.)

CSRF访问检查(CSRF access checking)

CSRF保护已经被集成到路由访问系统里面,并且被用作任何URLs执行动作或操作并且不会使用表单调用。在之前的Drupal版本中,在查询参数里面有必要添加一个密钥到URL中,并在callback或access中检查。现在你可以简单的在路由定义中添加一个’_csrf_token’到requirements节里面。按照如此做,系统将会自动添加一个token到查询字符串,并使用这个token为你做访问检查。(CSRF protection is now integrated into the routing access system, and should be used for any URLs that perform actions or operations that do not use a form callback. In previous versions of Drupal, it was necessary to add a generated token as a query parameter to a URL and check this token manually in either the callback or the access callback. Now you can simply use the '_csrf_token' requirement on a route definition. Doing so will automatically add a token to the query string, and this token will be checked for you.)

example:
  path: '/example'
  defaults:
    _controller: '\Drupal\example\Controller\ExampleController::content'
  requirements:
    _csrf_token: 'TRUE'

提示:为了让token被添加,链接必须通过路由名(‘example’)使用url_generator服务产生而不是人工构造路径。(Note that, in order for the token to be added, the link must be generated using the url_generator service via route name ("example" here) rather than as a manually constructed path.)