到现在为止,我们已经知道如何验证用户身份、如何查找用户角色以及如何判断用户可以访问系统的哪些部分。现在我们要在页面控制器中使用它们。
Note | |
---|---|
由于有很多方法用来处理访问控制,而且又因为大多数方法都止于特定应用。所以我们这里也只是列举两种应用。 |
实现访问控制的一种方法是把它作为页面控制器调度周期的一部分,让它自动地检测用户的权限并且提前改变被请求动作的行为。这种方法在每个动作调用之前自动地检测用户的权限。
相应的代码如下:
<?php abstract class Vendor_Controller_Page extends Solar_Controller_Page { public $user; protected function _setup() { parent::_setup(); $this->user = Solar_Registry::get('user'); } protected function _preAction() { parent::_preAction(); if (! $this->user->access->isAllowed($this, $this->_action)) { $this->_action = 'forbidden'; } } public function actionForbidden() { $this->_view = null; $this->_response->setStatusCode(403); $this->_response->setContent('Access denied.'); } }
在上面的代码中,我们使用当前Vendor类继承Solar_Controller_Page类。并且实现以下逻辑:
-
作为构造器的一部分,
_setup()
方法在对象注册表中获取Solar_User对象,因此我们就能得于当前用户的身份、角色和访问控制信息。(回忆一下,实例化Solar_User
对象时,同时会为我们实例化验证对象。) -
_preAction()
方法在所有动作之前运行。实现了逻辑的一部分,它检测当前用户是否有权限访问当前控制器和动作。如果没有,它将会改变$this->_action
的值,使得用户被重定向actionForbidden()
方法,而不是当前动作。 -
actionForbidden()
方法关闭视图和布局,设置HTTP状态码为"403 Forbidden"并且强制重置页面内容。(当然你可以创建forbidden.php
视图来设置响应内容,而不是直接设置响应内容。)
现在,当用户试图访问无权限的控制器和动作时,系统将会响应一个"403 Forbidden"页面。
上面的方法非常简便,但是它没有体现更细微的差别。有时候你可能需要在当前运行的动作中检查访问权限。如果是这样,你可能希望创建一个特定方法在动作内部检测访问权限。例如:
<?php abstract class Vendor_Controller_Page extends Solar_Controller_Page { public $user; protected function _setup() { parent::_setup(); $this->user = Solar_Registry::get('user'); } protected function _isUserAllowed() { if ($this->user->access->isAllowed($this, $this->_action)) { return true; } else { $this->_error('Access denied.'); $this->_response->setStatusCode(403); return false; } } } class Vendor_App_Foo extends Vendor_Controller_Page { public function actionFoo() { // ... perform preliminary logic ... // check access if (! $this->_isUserAllowed()) { return; } // ... rest of the action here ... } }
在这种方法中,我们做两件事。首先,使用当前Vendor类继承Solar_Controller_Page类。并且实现以下逻辑:
-
作为构造器的一部分,
_setup()
方法在对象注册表中获取Solar_User对象,因此我们就能得于当前用户的身份、角色和访问控制信息。(回忆一下,实例化Solar_User
对象时,同时会为我们实例化验证对象。) -
_isUserAllowed()
方法检测当前用户是否有权限访问当前控制器和动作。如果有,它返回真;但是如果没有,它调用Solar_Controller_Page::_error()方法且设置HTTP状态码为"403 Forbidden"。
基本的页面控制器弄好之后,我们修改actionBar()
方法,在逻辑中间检验用户权限。如果用户有权限,那么程序继续执行。如果没有,则退出当前动作,且在_isUserAllowed()
方法中调用_error()
方法并且自动渲染错误页面视图。