回答我自己的问题:
不,这毫无意义。那是因为
转发是在另一个控制器发生故障时调度控制器的一种模式
控制器已调度
Forward to another controller/action from module.php
)
这意味着,如果我有一个仅为经过身份验证的用户设计的用户页面(控制器),并且我调用了如下函数:
$name=$this->getUserName($userId);
无论如何,我找到了一个更好的解决方案,具有完全不同的行为,但结果相同(显然没有上述问题)。
然而,由于我最初的问题非常具体,为了清楚起见,我想更好地解释
:
我得到了一个acl脚本,该脚本在Dispatch之前运行,如果用户没有经过身份验证,它会将用户重定向到登录表单(role=guest)。
.
-
当用户通过www.site访问表单时。com/login,一旦通过身份验证,它们应该被重定向到www.site。com/user_主页
-
-
一旦用户通过身份验证,他们就不能访问www.site页面。com/login(因为没有用)。这意味着搜索此页面的用户应该被重定向到其他地方。
但我也从假设开始
-
如果没有直接联系到,就不应该有任何www.site的痕迹。com/登录到浏览器历史记录。
-
我到达页面站点。com/user/post/2016?tag=foo,但我未登录或会话已过期
-
-
-
但是,如果我通过浏览器的按钮返回,那么我请求的来源是www.site。com/登录,如第1点和第3点所定义,
我将被重定向到www.site。com/user_home失去返回站点的能力。com/user/post/2016?标记=foo(如果不是通过历史记录)。(这就是我尝试使用转发插件的原因)
我发现实现这一目标的解决方案是,除了使用自己动手转发过程外,还使用重定向插件,该过程与MVC的Routemach一起工作。
https://samsonasik.wordpress.com/2013/05/29/zend-framework-2-working-with-authenticationservice-and-db-session-save-handler/
与samsonasik代码的主要区别在于,我添加了一个名为authService的服务,该服务单独处理与身份验证相关的函数。
这只是为了使代码更具可读性/可重用性,因为我需要在身份验证时执行一些自定义逻辑(与我的应用程序设计相关)。
这里是我的结构的主要部分:
Application
Auth
->service
->authService
->aclService
Guest
->Controller
->guestHomeController
->loginAction
->singUpAction
->...
->...
User
->Controller
->userHomeController
->...
最后,代码:
namespace Auth;
use Zend\Mvc\MvcEvent;
class Module
{
public function onBootstrap(MvcEvent $e)
{
$app = $e->getApplication();
$sm = $app->getServiceManager();
$acl = $sm->get('aclService');
$acl->initAcl();
$e -> getApplication() -> getEventManager() -> attach(MvcEvent::EVENT_ROUTE, array($acl, 'checkAcl'));
}
[...]
}
路径:Auth/src/Auth/Service/AclService。php
namespace Auth\Service;
use Zend\Permissions\Acl\Acl;
use Zend\Permissions\Acl\Role\GenericRole as Role;
use Zend\Permissions\Acl\Resource\GenericResource as Resource;
use Zend\Mvc\MvcEvent;
class AclService {
protected $authService;
protected $config;
protected $acl;
protected $role;
public function __construct($authService,$config)
{
if(!$this->acl){$this->acl=new Acl();}
$this->authService = $authService;
$this->config = $config;
}
public function initAcl()
{
$this->acl->addRole(new Role('guest'));
[...]
$this->acl->addResource(new Resource('Guest\Controller\GuestHome'));
[...]
$this->acl->allow('role', 'controller','action');
[...]
}
public function checkAcl(MvcEvent $e)
{
$controller=$e -> getRouteMatch()->getParam('controller');
$action=$e -> getRouteMatch()->getParam('action');
$role=$this->getRole();
if (!$this->acl ->isAllowed($role, $controller, $action)){
//if user isn't authenticated...
if($role=='guest'){
//set current route controller and action (this doesn't modify the url, it's non a redirect)
$e -> getRouteMatch()->setParam('controller', 'Guest\Controller\GuestHome');
$e -> getRouteMatch()->setParam('action', 'login');
}//if
//if user is authenticated but has not the permission...
else{
$response = $e -> getResponse();
$response -> getHeaders() -> addHeaderLine('Location', $e -> getRequest() -> getBaseUrl() . '/404');
$response -> setStatusCode(404);
}//else
}//if
}
public function getRole()
{
if($this->authService->hasIdentity()){
[...]
}
else{$role='guest';}
return $role;
}
[...]
}
namespace Guest\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Zend\Form\Factory;
class GuestHomeController extends AbstractActionController
{
protected $authService;
protected $config;
protected $routeName;
public function __construct($authService, $config, $routeMatch)
{
$this->authService = $authService;
$this->config = $config;
$this->routeName = $routeMatch->getMatchedRouteName();
}
public function loginAction()
{
$forwardMessage=null;
//When users DOESN'T reach the form via www.site.com/login (they get forwarded), set a message to tell them what's going on
if($this->routeName!='login'){
$forwardMessage='You must be logged in to see this page!!!';
}
//This could probably be moved elsewhere and be triggered (when module is "Guest") on dispatch event with maximum priority (predispatch)
if ($this->authService->hasIdentity()) {
$this->dynamicRedirect();
}
$factory = new Factory();
$form = $factory->createForm($this->config['LoginForm']);
$request=$this->getRequest();
if ($request->isPost()) {
$form->setData($request->getPost());
if ($form->isValid()) {
$dataform = $form->getData();
$result=$this->authService->authenticate($dataform);
//result=status code
if($result===1){$this->dynamicRedirect();}
else{...}
}//$form->isValid()
}//$request->isPost()
$viewModel = new ViewModel();
$viewModel->setVariable('form', $form);
$viewModel->setVariable('error', $forwardMessage);
return $viewModel;
}
public function dynamicRedirect()
{
//if the form has been forwarded
if($this->routeName!='login'){
$url=$this->config['webhost'].$this->getRequest()->getRequestUri();
return $this->redirect()->toUrl($url);
}
else{return $this->redirect()->toRoute('userHome');}//else
}
[...]
}
如果我发现其他问题,我会更新这篇文章,但现在它很有魅力。