ZF2 - 检查每个操作中获取参数的权限
ZF2 - Checking permissions for get parameter in each action
我有一个名为 "TestController" 的控制器,里面有几个动作。对于每个操作,我都会收到一个获取参数 ("id")。
类似于:
test/action1/1
test/action1/2
test/action2/1
test/action3/1
...
由于这个参数很容易修改,所以我想检查一下这个id的权限。我是否必须在每个动作中都包含此检查方法,还是有其他方法?我知道我无法在构造函数中接收参数,但这样的方式会很好。
我目前的解决方案是在插件中有一个检查方法,并在每个动作中调用它,如下所示:
if(!$this->access()->checkAccess(..., $this->params()->fromRoute('id')) {
//redirect...
}
您可以使用 ACL(或 RBAC)进行这些检查。
使用 ACL,您可以(必须)声明应用程序的资源、使用该应用程序的角色以及角色访问资源的方式。
您可以首先将侦听器附加到控制器,在应用程序的 Module.php
class Module {
public function onBootstrap(\Zend\Mvc\MvcEvent $event) {
$application = $e->getApplication();
$serviceManager = $application->getServiceManager();
$sharedManager = $application->getEventManager()->getSharedManager();
$router = $serviceManager->get('router');
$request = $serviceManager->get('request');
$matchedRoute = $router->match($request);
if (null !== $matchedRoute) {
$sharedManager->attach(\Zend\Mvc\Controller\AbstractActionController::class, \Zend\Mvc\MvcEvent::EVENT_DISPATCH, function($event) use ($serviceManager) {
$serviceManager->get('ControllerPluginManager')->get('Application\Controller\Plugin\Acl')->doAuthorization($event);
}, 2
);
}
}
}
如您所见,我们将插件 Application\Controller\Plugin\Acl
附加到每个 Zend\Mvc\Controller\AbstractActionController
的 dispatch
事件。
然后你必须实施你的 ACLS。
这是一个简单的例子。
默认情况下,我更愿意拒绝访问所有资源,然后逐一允许访问它们。您也可以允许访问所有内容,然后拒绝访问单个资源,但这种方式您必须更加小心。如果您全部拒绝并忘记了某些内容,用户将无法访问它应该访问的内容。如果您允许所有内容而忘记了某些内容,则用户可能会看到他们不应该看到的内容。安全总比后悔好 ;)
namespace Application\Controller\Plugin;
class Acl extends \Zend\Mvc\Controller\Plugin\AbstractPlugin implements \Zend\ServiceManager\ServiceLocatorAwareInterface {
private $serviceLocator;
public function doAuthorization(\Zend\Mvc\MvcEvent $event) {
// Retrieve user role, if you have them or just use guest
$role = 'guest';
$resource = get_class($event->getTarget());
$action = $event->getRouteMatch()->getParams()['action'];
if (!$this->getAcl()->isAllowed($role, $resource, $action)) {
// Handle the access denied
// Could be a redirect to login/home page, or just an 404 page
}
}
public function getAcl() {
// Create the ACL object
$acl = new \Zend\Permissions\Acl\Acl();
// Add your roles
$acl->addRole(new \Zend\Permissions\Acl\Role\GenericRole('guest'));
// Add your resources
$acl->addResource(new Resource(\YourModule\Controller\YourController::class));
// By default, block access to all resources.
$acl->deny();
// Add, one by one, access to resources for all roles
$acl->allow('guest', \YourModule\Controller\YourController::class, ['action1', 'action2'], new \YourModule\Assertion\YourIdAssertion());
return $acl;
}
public function getServiceLocator() {
return $this->serviceLocator;
}
public function setServiceLocator(\Zend\ServiceManager\ServiceLocatorInterface $serviceLocator) {
$this->serviceLocator = $serviceLocator;
}
}
方法 allow
允许您定义这些参数:
- 角色(强制)
- 资源(必填)
- 操作(可选)
- 断言class(可选)
最后,声明了哪些角色可以访问特定资源的特定动作后,也可以告诉ACL一个"rule",如"access the action only if it this condition is met"。这些规则通过 Assertions
:
指定
use Zend\Permissions\Acl\Assertion\AssertionInterface;
use Zend\Permissions\Acl\Acl;
use Zend\Permissions\Acl\Role\RoleInterface as Role;
use Zend\Permissions\Acl\Resource\ResourceInterface as Resource;
class YourAssertion implements AssertionInterface {
public function __construct($serviceManager) {
// construct
}
public function assert(Acl $acl, Role $role = null, Resource $resource = null, $privilege = null) {
$isAllowed = false;
// Your logic to check if an user can access a specific id or not
// if(...){
// $isAllowed = true;
// }
return $isAllowed;
}
}
希望对您有所帮助!
我有一个名为 "TestController" 的控制器,里面有几个动作。对于每个操作,我都会收到一个获取参数 ("id")。 类似于:
test/action1/1
test/action1/2
test/action2/1
test/action3/1
...
由于这个参数很容易修改,所以我想检查一下这个id的权限。我是否必须在每个动作中都包含此检查方法,还是有其他方法?我知道我无法在构造函数中接收参数,但这样的方式会很好。
我目前的解决方案是在插件中有一个检查方法,并在每个动作中调用它,如下所示:
if(!$this->access()->checkAccess(..., $this->params()->fromRoute('id')) {
//redirect...
}
您可以使用 ACL(或 RBAC)进行这些检查。
使用 ACL,您可以(必须)声明应用程序的资源、使用该应用程序的角色以及角色访问资源的方式。
您可以首先将侦听器附加到控制器,在应用程序的 Module.php
class Module {
public function onBootstrap(\Zend\Mvc\MvcEvent $event) {
$application = $e->getApplication();
$serviceManager = $application->getServiceManager();
$sharedManager = $application->getEventManager()->getSharedManager();
$router = $serviceManager->get('router');
$request = $serviceManager->get('request');
$matchedRoute = $router->match($request);
if (null !== $matchedRoute) {
$sharedManager->attach(\Zend\Mvc\Controller\AbstractActionController::class, \Zend\Mvc\MvcEvent::EVENT_DISPATCH, function($event) use ($serviceManager) {
$serviceManager->get('ControllerPluginManager')->get('Application\Controller\Plugin\Acl')->doAuthorization($event);
}, 2
);
}
}
}
如您所见,我们将插件 Application\Controller\Plugin\Acl
附加到每个 Zend\Mvc\Controller\AbstractActionController
的 dispatch
事件。
然后你必须实施你的 ACLS。
这是一个简单的例子。 默认情况下,我更愿意拒绝访问所有资源,然后逐一允许访问它们。您也可以允许访问所有内容,然后拒绝访问单个资源,但这种方式您必须更加小心。如果您全部拒绝并忘记了某些内容,用户将无法访问它应该访问的内容。如果您允许所有内容而忘记了某些内容,则用户可能会看到他们不应该看到的内容。安全总比后悔好 ;)
namespace Application\Controller\Plugin;
class Acl extends \Zend\Mvc\Controller\Plugin\AbstractPlugin implements \Zend\ServiceManager\ServiceLocatorAwareInterface {
private $serviceLocator;
public function doAuthorization(\Zend\Mvc\MvcEvent $event) {
// Retrieve user role, if you have them or just use guest
$role = 'guest';
$resource = get_class($event->getTarget());
$action = $event->getRouteMatch()->getParams()['action'];
if (!$this->getAcl()->isAllowed($role, $resource, $action)) {
// Handle the access denied
// Could be a redirect to login/home page, or just an 404 page
}
}
public function getAcl() {
// Create the ACL object
$acl = new \Zend\Permissions\Acl\Acl();
// Add your roles
$acl->addRole(new \Zend\Permissions\Acl\Role\GenericRole('guest'));
// Add your resources
$acl->addResource(new Resource(\YourModule\Controller\YourController::class));
// By default, block access to all resources.
$acl->deny();
// Add, one by one, access to resources for all roles
$acl->allow('guest', \YourModule\Controller\YourController::class, ['action1', 'action2'], new \YourModule\Assertion\YourIdAssertion());
return $acl;
}
public function getServiceLocator() {
return $this->serviceLocator;
}
public function setServiceLocator(\Zend\ServiceManager\ServiceLocatorInterface $serviceLocator) {
$this->serviceLocator = $serviceLocator;
}
}
方法 allow
允许您定义这些参数:
- 角色(强制)
- 资源(必填)
- 操作(可选)
- 断言class(可选)
最后,声明了哪些角色可以访问特定资源的特定动作后,也可以告诉ACL一个"rule",如"access the action only if it this condition is met"。这些规则通过 Assertions
:
use Zend\Permissions\Acl\Assertion\AssertionInterface;
use Zend\Permissions\Acl\Acl;
use Zend\Permissions\Acl\Role\RoleInterface as Role;
use Zend\Permissions\Acl\Resource\ResourceInterface as Resource;
class YourAssertion implements AssertionInterface {
public function __construct($serviceManager) {
// construct
}
public function assert(Acl $acl, Role $role = null, Resource $resource = null, $privilege = null) {
$isAllowed = false;
// Your logic to check if an user can access a specific id or not
// if(...){
// $isAllowed = true;
// }
return $isAllowed;
}
}
希望对您有所帮助!