Php Symfony2自定义异常和身份验证令牌

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

[注意]也请参阅最终解决方法,向下滚动

经过12个小时的头痛和阅读大量资料后,我放弃了,并请求他人帮助我解决“安全上下文不包含身份验证令牌。一个可能的原因可能是没有为此URL配置防火墙。”问题

如何将安全上下文正确地传递给自定义处理程序

我有以下设置:

  • 环境:产品
  • 调试:false
security.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 ]
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,抱歉。现在,我将根据您的建议创建一个解决方案(在第一条评论中添加)。谢谢