Php Symfony2自定义异常和身份验证令牌
[注意]也请参阅最终解决方法,向下滚动 经过12个小时的头痛和阅读大量资料后,我放弃了,并请求他人帮助我解决“安全上下文不包含身份验证令牌。一个可能的原因可能是没有为此URL配置防火墙。”问题 如何将安全上下文正确地传递给自定义处理程序 我有以下设置:Php Symfony2自定义异常和身份验证令牌,php,security,exception,symfony,token,Php,Security,Exception,Symfony,Token,[注意]也请参阅最终解决方法,向下滚动 经过12个小时的头痛和阅读大量资料后,我放弃了,并请求他人帮助我解决“安全上下文不包含身份验证令牌。一个可能的原因可能是没有为此URL配置防火墙。”问题 如何将安全上下文正确地传递给自定义处理程序 我有以下设置: 环境:产品 调试:false security.yml jms_security_extra: secure_all_services: false expressions: true security: encod
- 环境:产品
- 调试:false
jms_security_extra:
secure_all_services: false
expressions: true
security:
encoders:
Symfony\Component\Security\Core\User\User: plaintext
path\to\SsoAccount: plaintext
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
sso:
id: sso_account_provider
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
sso:
pattern: ^/
logout:
path: sso_logout
target: homepage
anonymous: ~
access_control: ~
# Twig Configuration
twig:
exception_controller: "acme.controller.exception_controller:showAction"
debug: "%kernel.debug%"
strict_variables: "%kernel.debug%"
globals:
project_url: "%cfg_project_url%"
sso_server: "%cfg_sso_server%"
sso_server_admin: "%cfg_sso_server_admin%"
google_drive_api_key: "%cfg_google_drive_api_key%"
oauth_client_id: "%cfg_oauth_client_id%"
form:
resources:
- "MainBundle:Form:fields.html.twig"
services:
acme.controller.exception_controller:
parent: twig.controller.exception
class: Acme\MainBundle\Controller\ExceptionController
arguments: ["@security.context"]
calls:
- [ 'setContainer', ['@service_container']]
- [ 'setSecurityContext', ['@security.context']]
services:
acme.controller.exception_controller:
class: Acme\MainBundle\EventListener\NotFoundRouteListener
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
arguments: [ @router, @service_container, @kernel ]
config.yml
jms_security_extra:
secure_all_services: false
expressions: true
security:
encoders:
Symfony\Component\Security\Core\User\User: plaintext
path\to\SsoAccount: plaintext
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
sso:
id: sso_account_provider
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
sso:
pattern: ^/
logout:
path: sso_logout
target: homepage
anonymous: ~
access_control: ~
# Twig Configuration
twig:
exception_controller: "acme.controller.exception_controller:showAction"
debug: "%kernel.debug%"
strict_variables: "%kernel.debug%"
globals:
project_url: "%cfg_project_url%"
sso_server: "%cfg_sso_server%"
sso_server_admin: "%cfg_sso_server_admin%"
google_drive_api_key: "%cfg_google_drive_api_key%"
oauth_client_id: "%cfg_oauth_client_id%"
form:
resources:
- "MainBundle:Form:fields.html.twig"
services:
acme.controller.exception_controller:
parent: twig.controller.exception
class: Acme\MainBundle\Controller\ExceptionController
arguments: ["@security.context"]
calls:
- [ 'setContainer', ['@service_container']]
- [ 'setSecurityContext', ['@security.context']]
services:
acme.controller.exception_controller:
class: Acme\MainBundle\EventListener\NotFoundRouteListener
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
arguments: [ @router, @service_container, @kernel ]
Acme/MainBundle/Controller/ExceptionController.php
<?php
namespace Acme\MainBundle\Controller;
use Symfony\Bundle\TwigBundle\Controller\ExceptionController as BaseExceptionController;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\FlattenException;
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
use Symfony\Component\Security\Core\SecurityContext;
class ExceptionController extends BaseExceptionController
{
protected $securityContext;
protected $container;
public function setContainer(ContainerInterface $container)
{
$this->container = $container;
}
public function setSecurityContext(SecurityContext $context)
{
$this->securityContext = $context;
}
public function showAction(
Request $request,
FlattenException $exception,
DebugLoggerInterface $logger = null,
$format = 'html'
) {
$this->exceptionClass = $exception->getClass();
return parent::showAction($request, $exception, $logger, $format);
}
protected function findTemplate(Request $request, $format, $code, $debug)
{
/*********************/
/** PROBLEM IS HERE **/
//$user = $this->securityContext->isGranted('ROLE_USER');
/** PROBLEM IS HERE **/
/*********************/
if (!$debug) {
return 'MainBundle:Main:error404.html.twig';
}
return parent::findTemplate($request, $format, $code, $debug);
}
}
/**
*/
public function error404Action()
{
/** ALWAYS return null **/
$getUser = $this->getUser();
/***********************/
if (!empty($getUser)) {
$account = $this->getUser()->getAccountInfo();
$user = $account->Account["0"]->user;
return $this->render(
'MainBundle:Main:error404_loggedin.html.twig',
array(
'account' => $account,
'user' => $user,
)
);
}
return $this->render(
'MainBundle:Main:error404_not_loggedin.html.twig',
array()
);
}
/**
* @Route("/404", name="publicError404")
*/
public function publicError404Action()
{
$response = new Response();
$response->setStatusCode(404);
$templateFile = 'MainBundle:Main:error404_not_loggedin.html.twig';
$templateData = array();
$getUser = $this->getUser();
if (!empty($getUser)) {
$templateFile = 'MainBundle:Main:error404_loggedin.html.twig';
$account = $this->getUser()->getAccountInfo();
$user = $account->Account["0"]->user;
$templateData['account'] = $account;
$templateData['user'] = $user;
}
$templateData['token'] = $this->getRequest()->getSession()->getId();
$templateData['sso'] = $this->container->getParameter('sso_token');
$templateData['timestamp'] = time(); //date(DATE_RFC822)
return $this->render($templateFile, $templateData, $response);
}
<?php
namespace Acme\MainBundle\EventListener;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Routing\Router;
class NotFoundRouteListener
{
protected $container;
protected $router;
protected $kernel;
public function __construct(Router $router, ContainerInterface $container, Kernel $kernel)
{
$this->router = $router;
$this->container = $container;
$this->kernel = $kernel;
}
public function onKernelRequest(GetResponseEvent $event)
{
$isProduction = ($this->kernel->getEnvironment() == "prod") ? true : false;
$isDebug = ($this->kernel->isDebug() == true) ? : false;
$routeName = $this->container->get('request')->get('_route');
/**
* Display only if:
* - env = prod
* - debug = false
* - route = empty
*/
if ($isProduction && !$isDebug && empty($routeName)) {
$url = $this->router->generate('publicError404');
$event->setResponse(new RedirectResponse($url));
}
}
}
Acme/MainBundle/Controller/MainController.php
<?php
namespace Acme\MainBundle\Controller;
use Symfony\Bundle\TwigBundle\Controller\ExceptionController as BaseExceptionController;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\FlattenException;
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
use Symfony\Component\Security\Core\SecurityContext;
class ExceptionController extends BaseExceptionController
{
protected $securityContext;
protected $container;
public function setContainer(ContainerInterface $container)
{
$this->container = $container;
}
public function setSecurityContext(SecurityContext $context)
{
$this->securityContext = $context;
}
public function showAction(
Request $request,
FlattenException $exception,
DebugLoggerInterface $logger = null,
$format = 'html'
) {
$this->exceptionClass = $exception->getClass();
return parent::showAction($request, $exception, $logger, $format);
}
protected function findTemplate(Request $request, $format, $code, $debug)
{
/*********************/
/** PROBLEM IS HERE **/
//$user = $this->securityContext->isGranted('ROLE_USER');
/** PROBLEM IS HERE **/
/*********************/
if (!$debug) {
return 'MainBundle:Main:error404.html.twig';
}
return parent::findTemplate($request, $format, $code, $debug);
}
}
/**
*/
public function error404Action()
{
/** ALWAYS return null **/
$getUser = $this->getUser();
/***********************/
if (!empty($getUser)) {
$account = $this->getUser()->getAccountInfo();
$user = $account->Account["0"]->user;
return $this->render(
'MainBundle:Main:error404_loggedin.html.twig',
array(
'account' => $account,
'user' => $user,
)
);
}
return $this->render(
'MainBundle:Main:error404_not_loggedin.html.twig',
array()
);
}
/**
* @Route("/404", name="publicError404")
*/
public function publicError404Action()
{
$response = new Response();
$response->setStatusCode(404);
$templateFile = 'MainBundle:Main:error404_not_loggedin.html.twig';
$templateData = array();
$getUser = $this->getUser();
if (!empty($getUser)) {
$templateFile = 'MainBundle:Main:error404_loggedin.html.twig';
$account = $this->getUser()->getAccountInfo();
$user = $account->Account["0"]->user;
$templateData['account'] = $account;
$templateData['user'] = $user;
}
$templateData['token'] = $this->getRequest()->getSession()->getId();
$templateData['sso'] = $this->container->getParameter('sso_token');
$templateData['timestamp'] = time(); //date(DATE_RFC822)
return $this->render($templateFile, $templateData, $response);
}
<?php
namespace Acme\MainBundle\EventListener;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Routing\Router;
class NotFoundRouteListener
{
protected $container;
protected $router;
protected $kernel;
public function __construct(Router $router, ContainerInterface $container, Kernel $kernel)
{
$this->router = $router;
$this->container = $container;
$this->kernel = $kernel;
}
public function onKernelRequest(GetResponseEvent $event)
{
$isProduction = ($this->kernel->getEnvironment() == "prod") ? true : false;
$isDebug = ($this->kernel->isDebug() == true) ? : false;
$routeName = $this->container->get('request')->get('_route');
/**
* Display only if:
* - env = prod
* - debug = false
* - route = empty
*/
if ($isProduction && !$isDebug && empty($routeName)) {
$url = $this->router->generate('publicError404');
$event->setResponse(new RedirectResponse($url));
}
}
}
“not Loggin”(未登录)错误404没有任何问题,因为没有为其添加安全性,但为登录成员显示不同的错误让我感到痛苦,因此请提供建议。谢谢
*最终解决方法*
Acme/MainBundle/Controller/MainController.php
<?php
namespace Acme\MainBundle\Controller;
use Symfony\Bundle\TwigBundle\Controller\ExceptionController as BaseExceptionController;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\FlattenException;
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
use Symfony\Component\Security\Core\SecurityContext;
class ExceptionController extends BaseExceptionController
{
protected $securityContext;
protected $container;
public function setContainer(ContainerInterface $container)
{
$this->container = $container;
}
public function setSecurityContext(SecurityContext $context)
{
$this->securityContext = $context;
}
public function showAction(
Request $request,
FlattenException $exception,
DebugLoggerInterface $logger = null,
$format = 'html'
) {
$this->exceptionClass = $exception->getClass();
return parent::showAction($request, $exception, $logger, $format);
}
protected function findTemplate(Request $request, $format, $code, $debug)
{
/*********************/
/** PROBLEM IS HERE **/
//$user = $this->securityContext->isGranted('ROLE_USER');
/** PROBLEM IS HERE **/
/*********************/
if (!$debug) {
return 'MainBundle:Main:error404.html.twig';
}
return parent::findTemplate($request, $format, $code, $debug);
}
}
/**
*/
public function error404Action()
{
/** ALWAYS return null **/
$getUser = $this->getUser();
/***********************/
if (!empty($getUser)) {
$account = $this->getUser()->getAccountInfo();
$user = $account->Account["0"]->user;
return $this->render(
'MainBundle:Main:error404_loggedin.html.twig',
array(
'account' => $account,
'user' => $user,
)
);
}
return $this->render(
'MainBundle:Main:error404_not_loggedin.html.twig',
array()
);
}
/**
* @Route("/404", name="publicError404")
*/
public function publicError404Action()
{
$response = new Response();
$response->setStatusCode(404);
$templateFile = 'MainBundle:Main:error404_not_loggedin.html.twig';
$templateData = array();
$getUser = $this->getUser();
if (!empty($getUser)) {
$templateFile = 'MainBundle:Main:error404_loggedin.html.twig';
$account = $this->getUser()->getAccountInfo();
$user = $account->Account["0"]->user;
$templateData['account'] = $account;
$templateData['user'] = $user;
}
$templateData['token'] = $this->getRequest()->getSession()->getId();
$templateData['sso'] = $this->container->getParameter('sso_token');
$templateData['timestamp'] = time(); //date(DATE_RFC822)
return $this->render($templateFile, $templateData, $response);
}
<?php
namespace Acme\MainBundle\EventListener;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Routing\Router;
class NotFoundRouteListener
{
protected $container;
protected $router;
protected $kernel;
public function __construct(Router $router, ContainerInterface $container, Kernel $kernel)
{
$this->router = $router;
$this->container = $container;
$this->kernel = $kernel;
}
public function onKernelRequest(GetResponseEvent $event)
{
$isProduction = ($this->kernel->getEnvironment() == "prod") ? true : false;
$isDebug = ($this->kernel->isDebug() == true) ? : false;
$routeName = $this->container->get('request')->get('_route');
/**
* Display only if:
* - env = prod
* - debug = false
* - route = empty
*/
if ($isProduction && !$isDebug && empty($routeName)) {
$url = $this->router->generate('publicError404');
$event->setResponse(new RedirectResponse($url));
}
}
}
app/config/config.yml
jms_security_extra:
secure_all_services: false
expressions: true
security:
encoders:
Symfony\Component\Security\Core\User\User: plaintext
path\to\SsoAccount: plaintext
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
sso:
id: sso_account_provider
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
sso:
pattern: ^/
logout:
path: sso_logout
target: homepage
anonymous: ~
access_control: ~
# Twig Configuration
twig:
exception_controller: "acme.controller.exception_controller:showAction"
debug: "%kernel.debug%"
strict_variables: "%kernel.debug%"
globals:
project_url: "%cfg_project_url%"
sso_server: "%cfg_sso_server%"
sso_server_admin: "%cfg_sso_server_admin%"
google_drive_api_key: "%cfg_google_drive_api_key%"
oauth_client_id: "%cfg_oauth_client_id%"
form:
resources:
- "MainBundle:Form:fields.html.twig"
services:
acme.controller.exception_controller:
parent: twig.controller.exception
class: Acme\MainBundle\Controller\ExceptionController
arguments: ["@security.context"]
calls:
- [ 'setContainer', ['@service_container']]
- [ 'setSecurityContext', ['@security.context']]
services:
acme.controller.exception_controller:
class: Acme\MainBundle\EventListener\NotFoundRouteListener
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
arguments: [ @router, @service_container, @kernel ]
Acme/MainBundle/EventListener/NotFoundRouteListener.php
<?php
namespace Acme\MainBundle\Controller;
use Symfony\Bundle\TwigBundle\Controller\ExceptionController as BaseExceptionController;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\FlattenException;
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
use Symfony\Component\Security\Core\SecurityContext;
class ExceptionController extends BaseExceptionController
{
protected $securityContext;
protected $container;
public function setContainer(ContainerInterface $container)
{
$this->container = $container;
}
public function setSecurityContext(SecurityContext $context)
{
$this->securityContext = $context;
}
public function showAction(
Request $request,
FlattenException $exception,
DebugLoggerInterface $logger = null,
$format = 'html'
) {
$this->exceptionClass = $exception->getClass();
return parent::showAction($request, $exception, $logger, $format);
}
protected function findTemplate(Request $request, $format, $code, $debug)
{
/*********************/
/** PROBLEM IS HERE **/
//$user = $this->securityContext->isGranted('ROLE_USER');
/** PROBLEM IS HERE **/
/*********************/
if (!$debug) {
return 'MainBundle:Main:error404.html.twig';
}
return parent::findTemplate($request, $format, $code, $debug);
}
}
/**
*/
public function error404Action()
{
/** ALWAYS return null **/
$getUser = $this->getUser();
/***********************/
if (!empty($getUser)) {
$account = $this->getUser()->getAccountInfo();
$user = $account->Account["0"]->user;
return $this->render(
'MainBundle:Main:error404_loggedin.html.twig',
array(
'account' => $account,
'user' => $user,
)
);
}
return $this->render(
'MainBundle:Main:error404_not_loggedin.html.twig',
array()
);
}
/**
* @Route("/404", name="publicError404")
*/
public function publicError404Action()
{
$response = new Response();
$response->setStatusCode(404);
$templateFile = 'MainBundle:Main:error404_not_loggedin.html.twig';
$templateData = array();
$getUser = $this->getUser();
if (!empty($getUser)) {
$templateFile = 'MainBundle:Main:error404_loggedin.html.twig';
$account = $this->getUser()->getAccountInfo();
$user = $account->Account["0"]->user;
$templateData['account'] = $account;
$templateData['user'] = $user;
}
$templateData['token'] = $this->getRequest()->getSession()->getId();
$templateData['sso'] = $this->container->getParameter('sso_token');
$templateData['timestamp'] = time(); //date(DATE_RFC822)
return $this->render($templateFile, $templateData, $response);
}
<?php
namespace Acme\MainBundle\EventListener;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Routing\Router;
class NotFoundRouteListener
{
protected $container;
protected $router;
protected $kernel;
public function __construct(Router $router, ContainerInterface $container, Kernel $kernel)
{
$this->router = $router;
$this->container = $container;
$this->kernel = $kernel;
}
public function onKernelRequest(GetResponseEvent $event)
{
$isProduction = ($this->kernel->getEnvironment() == "prod") ? true : false;
$isDebug = ($this->kernel->isDebug() == true) ? : false;
$routeName = $this->container->get('request')->get('_route');
/**
* Display only if:
* - env = prod
* - debug = false
* - route = empty
*/
if ($isProduction && !$isDebug && empty($routeName)) {
$url = $this->router->generate('publicError404');
$event->setResponse(new RedirectResponse($url));
}
}
}
安全逻辑在路由逻辑之后执行(在2.1之前,它是在之前执行的)。这意味着路由器抛出的404错误不能使用安全性,因为还没有关于安全性的信息
在安全信息可用的情况下,您还可以在控制器中抛出404错误。要使其在任何情况下都可用,请检查安全上下文是否可用并已设置,如果不可用,只需呈现未登录的模板为什么XML文件中有YAML?它们是.yml,抱歉。现在,我将根据您的建议创建一个解决方案(在第一条评论中添加)。谢谢