我建议制作一个禁止控制器列表,然后在应用控制器beforeFilter
处理程序中检查它,以防当前请求来自子域:
protected $_forbiddenSubdomainControllers = array
(
'about',
'home',
'pricing',
'signup'
);
public function beforeFilter()
{
parent::beforeFilter();
if($this->checkSubdomain() &&
in_array($this->request->params['controller'], $this->_forbiddenSubdomainControllers))
{
throw new ForbiddenException('This URL is inaccessible');
}
}
public function checkSubdomain()
{
if ($_SERVER['HTTP_HOST'] != 'domain.com')
{
$domain_parts = explode('.',$_SERVER['HTTP_HOST']);
if (count($domain_parts) != 3) exit('Invalid url');
$subdomain = $domain_parts[0];
$this->loadModel('Subsite');
$subsites = $this->Subsite->find('all', array('conditions'=>array('domain'=>$subdomain)));
if(empty($subsites))
{
throw new NotFoundException('Subsite not found');
}
return true;
}
return false;
}
请注意,我已经更改了您的checkSubdomain
方法,以便它返回true
或false
取决于请求是否来自(有效)子域,并且我还更改了您的exit
调用以引发错误,这是 CakePHP 处理此类情况的首选方式.
如果您想允许某些子域使用其中一些“特殊”控制器,那么我建议将允许的控制器存储在数据库中并将它们与Subsite
模型相关联,然后您可以在检查中包含这些名称。
编辑 (05.11.2012)
仅在从子域请求时才要求对特定控件进行身份验证,例如可以通过使用AuthComponent::allow
. 在Home
控制器beforeFilter
回调中,您可以检查子域,然后适当地允许/拒绝未经身份验证的访问。例如,如果请求不是来自子域,则允许所有操作:
public function beforeFilter()
{
parent::beforeFilter();
if(!$this->checkSubdomain())
{
$this->Auth->allow('*');
}
}
考虑到您限制对特定操作的访问的新要求,我想说,根据您的应用程序的复杂性,限制/授予访问权限可能是ACL的一项工作。
相反,“手动”执行此操作,我的第一个示例可以通过操作进行扩展,例如:
protected $_denyAccessMap = array
(
'about',
'home',
'pricing',
'users' => array
(
'signup'
)
);
public function beforeFilter()
{
parent::beforeFilter();
if($this->checkSubdomain())
{
$controller = $this->request->params['controller'];
$action = $this->request->params['action'];
if(in_array($controller, $this->_denyAccessMap) ||
(array_key_exists($controller, $this->_denyAccessMap) && in_array($action, $this->_denyAccessMap[$controller])))
{
throw new ForbiddenException('This URL is inaccessible');
}
}
}
这将拒绝对控制器about
、home
和pricing
、和users
控制器signup
操作的访问。
如前所述,这也可以使用 ACL 来完成,并且由于您说您需要授予某些子域更多的访问权限,这可能是更好的选择,它可以让您动态控制访问限制。看看Simple Acl 控制的应用程序教程,你可以很容易地使用它,你只需要用Group
你的模型替换Subsite
模型。
这样,您可以授予特定子站点以及与该子站点关联的用户对特定操作Subsite
的访问权限,例如允许id
1
访问除Users
控制器subscribe
方法之外的所有控制器:
$this->Subsite->id = 1;
$this->Acl->allow($this->Subsite, 'controllers');
$this->Acl->deny($this->Subsite, 'controllers/User/subscribe');
或者相反,阻止对Users
控制器的访问,期望特定login
和passwordRecovery
操作:
$this->Acl->allow($this->Subsite, 'controllers');
$this->Acl->deny($this->Subsite, 'controllers/User');
$this->Acl->allow($this->Subsite, 'controllers/User/login');
$this->Acl->allow($this->Subsite, 'controllers/User/passwordRecovery');
例如,检查是否允许访问可以在应用程序控制器beforeFilter
回调中完成:
public function beforeFilter()
{
parent::beforeFilter();
$subsite = $this->checkSubdomain();
if(!empty($subsite))
{
$aco = 'controllers/' . $this->name . '/' . $this->request->params['action'];
if($this->Acl->check($subsite, $aco))
{
throw new ForbiddenException('This URL is inaccessible');
}
}
}
public function checkSubdomain()
{
if ($_SERVER['HTTP_HOST'] != 'domain.com')
{
$domain_parts = explode('.',$_SERVER['HTTP_HOST']);
if (count($domain_parts) != 3) exit('Invalid url');
$subdomain = $domain_parts[0];
$this->loadModel('Subsite');
$subsite = $this->Subsite->find('first', array('conditions'=>array('domain'=>$subdomain)));
if(empty($subsite))
{
throw new NotFoundException('Subsite not found');
}
return $subsite;
}
return false;
}
请注意,我已经更改了checkSubdomain
方法,以便它返回find
结果,或者false
可以轻松地将其用于 ACL 检查。