分层身份验证-使用listeneraggregate时重定向到登录页面



我正在将一个应用程序从ZF2/3迁移到Laminas。我已经将身份验证从Module.php引导程序移到了聚合器中,如果用户没有登录某些路由,我想重定向到登录页面。这最初工作得很好,但在迁移后我遇到了麻烦——它现在重定向了20到30次,并导致"错误";页面没有正确重定向";错误

My Module.php onBoostrap方法:

class Module implements ConfigProviderInterface
{
/**
* @param $event
*/
public function onBootstrap(MvcEvent $event)
{
/** @var ApplicationInterface $application*/
$application = $event->getApplication();
/** @var TemplateMapResolver $templateMapResolver */
$templateMapResolver = $application->getServiceManager()->get(
'ViewTemplateMapResolver'
);
// Create and register layout listener
$listener = new LayoutListener($templateMapResolver);
$listener->attach($application->getEventManager());
//Create and register Authentication listener
$authenticationListener = new AuthenticationListener();
$authenticationListener->attach($application->getEventManager());
}
}

AuthenticationListener类:

class AuthenticationListener extends AbstractListenerAggregate
{
/**
* @param EventManagerInterface $events
* @param int $priority
*/
public function attach(EventManagerInterface $events, $priority = 1)
{
$this->listeners[] = $events->attach(
MvcEvent::EVENT_DISPATCH,
[$this, 'userHasAuthentication']
);
}
/**
* @param MvcEvent $event
*/
public function userHasAuthentication(MvcEvent $event)
{
$authenticationService   = $event->getApplication()->getServiceManager()->get(AuthenticationService::class);
if($authenticationService->hasIdentity() === false){
$event->stopPropagation(true);
// ? how to redirect
}
return true;
}
}

我尝试了以下重定向方法,这些方法最终仍然是"重定向";没有正确重定向";后果内部AuthenticationListener::userHasAuthentication:

if($authenticationService->hasIdentity() === false){
$event->stopPropagation(true);
/**@var AbstractActionController $target*/
$target = $event->getTarget();
return $target->redirect()->toRoute('auth.login');     
}

if($authenticationService->hasIdentity() === false){
$event->stopPropagation(true);
/**@var AbstractActionController $target*/
$target = $event->getTarget();
$response = $target->getResponse();
$response->getHeaders()->addHeaderLine('Location', '/login');
$response->setStatusCode(403);
$response->sendHeaders();
return $response;     
}

实现这一目标的正确方法是什么?

我认为您得到了重定向循环,因为这个监听器也在/login页面上触发。在重定向之前,您必须检查当前路由。

public function userHasAuthentication(MvcEvent $e)
{
$routeMatch = $e->getRouteMatch();
if ($routeMatch) {
$routeName = $routeMatch->getMatchedRouteName();
if ($routeName !== 'login' && $routeMatch->getParam('loginRequired',true)) {
$auth = $e->getApplication()->getServiceManager()->get(AuthenticationServiceInterface::class);
if ($auth->hasIdentity() === false) {
$response = new LaminasHttpPhpEnvironmentResponse();
$response->getHeaders()->addHeaderLine('Location', "/login");
$response->setStatusCode(302);
return $response;
}
}
}
}

在路由参数"loginRequired"上添加条件可以禁用所选路径的重定向,在路由配置的"defaults"部分添加'loginRequired'=>false

顺便说一句,如果你使用更高的侦听器优先级,或者附加MvcEvent::ROUTE,你可以通过更改路由匹配在每个路径上显示登录页面

public function userHasAuthentication(MvcEvent $e)
{
$routeMatch = $e->getRouteMatch();
if ($routeMatch) {
$routeName = $routeMatch->getMatchedRouteName();
if ($routeName !== 'login'
&& $routeName !== 'logout'
&& $routeMatch->getParam('loginRequired', true) !== false
) {
$auth = $e->getApplication()->getServiceManager()->get(AuthenticationServiceInterface::class);
if ($auth->hasIdentity() === false) {
$routeMatch->setParam('controller', LoginController::class);
$routeMatch->setParam('action', 'login');
if ($routeName !== 'home') {
$e->getResponse()->setStatusCode(401);
}
}
}
}
}

登录操作时添加

if ($this->auth->hasIdentity()) {
$this->checkTourDismiss($this->auth->getIdentity());
if (isset($_SERVER['REQUEST_URI'])
&& !in_array($_SERVER['REQUEST_URI'], ['/', '/login'])
) {
$this->redirect()->toUrl($_SERVER['REQUEST_URI']);
} else {
$this->redirect()->toRoute('home');    
}
}

最后,所以在登录后,用户会停留在他开始使用的URL上。

最新更新