Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[Security] Clarify the purpose of access denied handler (and entry point)#14045

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
wouterj merged 1 commit intosymfony:4.4fromwouterj:security/access-denied
Oct 31, 2020
Merged
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
181 changes: 166 additions & 15 deletionssecurity/access_denied_handler.rst
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,116 @@
.. index::
single: Security; Creating a Custom Access Denied Handler

How toCreate a CustomAccess DeniedHandler
============================================
How toCustomizeAccess DeniedResponses
========================================

When your application throws an ``AccessDeniedException``, you can handle this exception
with a service to return a custom response.
In Symfony, you can throw an
:class:`Symfony\\Component\\Security\\Core\\Exception\\AccessDeniedException`
to disallow access to the user. Symfony will handle this exception and
generates a response based on the authentication state:

First, create a class that implements
* **If the user is not authenticated** (or authenticated anonymously), an
authentication entry point is used to generated a response (typically
a redirect to the login page or an *401 Unauthorized* response);
* **If the user is authenticated, but does not have the required
permissions**, a *403 Forbidden* response is generated.

Customize the Unauthorized Response
-----------------------------------

You need to create a class that implements
:class:`Symfony\\Component\\Security\\Http\\EntryPoint\\AuthenticationEntryPointInterface`.
This interface has one method (``start()``) that is called whenever an
unauthenticated user tries to access a protected resource::

// src/Security/AuthenticationEntryPoint.php
namespace App\Security;

use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;

class AuthenticationEntryPoint implements AuthenticationEntryPointInterface
{
private $urlGenerator;
private $session;

public function __construct(UrlGeneratorInterface $urlGenerator, SessionInterface $session)
{
$this->urlGenerator = $urlGenerator;
$this->session = $session;
}

public function start(Request $request, AuthenticationException $authException = null): RedirectResponse
{
// add a custom flash message and redirect to the login page
$this->session->getFlashBag()->add('note', 'You have to login in order to access this page.');

return new RedirectResponse($this->urlGenerator->generate('security_login'));
}
}

That's it if you're using the :ref:`default services.yaml configuration <service-container-services-load-example>`.
Otherwise, you have to register this service in the container.

Now, configure this service ID as the entry point for the firewall:

.. configuration-block::

.. code-block:: yaml

# config/packages/security.yaml
firewalls:
# ...

main:
# ...
entry_point: App\Security\AuthenticationEntryPoint

.. code-block:: xml

<!-- config/packages/security.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<srv:container xmlns="http://symfony.com/schema/dic/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:srv="http://symfony.com/schema/dic/services"
xsi:schemaLocation="http://symfony.com/schema/dic/services
https://symfony.com/schema/dic/services/services-1.0.xsd">

<config>
<firewall name="main"
entry-point="App\Security\AuthenticationEntryPoint"
>
<!-- ... -->
</firewall>
</config>
</srv:container>

.. code-block:: php

// config/packages/security.php
use App\Security\AuthenticationEntryPoint;

$container->loadFromExtension('security', [
'firewalls' => [
'main' => [
// ...
'entry_point' => AuthenticationEntryPoint::class,
],
],
]);

Customize the Forbidden Response
--------------------------------

Create a class that implements
:class:`Symfony\\Component\\Security\\Http\\Authorization\\AccessDeniedHandlerInterface`.
This interface defines one method called ``handle()`` where you can implement whatever
logic that should run when access is denied for the current user (e.g. send a
mail, log a message, or generally return a custom response)::
This interface defines one method called ``handle()`` where you can
implement whatever logic that should execute when access is denied for the
current user (e.g. send a mail, log a message, or generally return a custom
response)::

namespace App\Security;

Expand DownExpand Up@@ -49,11 +148,21 @@ configure it under your firewall:
.. code-block:: xml

<!-- config/packages/security.xml -->
<config>
<firewall name="main">
<access-denied-handler>App\Security\AccessDeniedHandler</access-denied-handler>
</firewall>
</config>
<?xml version="1.0" encoding="UTF-8"?>
<srv:container xmlns="http://symfony.com/schema/dic/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:srv="http://symfony.com/schema/dic/services"
xsi:schemaLocation="http://symfony.com/schema/dic/services
https://symfony.com/schema/dic/services/services-1.0.xsd">

<config>
<firewall name="main"
access-denied-handler="App\Security\AccessDeniedHandler"
>
<!-- ... -->
</firewall>
</config>
</srv:container>

.. code-block:: php

Expand All@@ -69,5 +178,47 @@ configure it under your firewall:
],
]);

That's it! Any ``AccessDeniedException`` thrown by code under the ``main`` firewall
will now be handled by your service.
Customizing All Access Denied Responses
---------------------------------------

In some cases, you might want to customize both responses or do a specific
action (e.g. logging) for each ``AccessDeniedException``. In this case,
configure a :ref:`kernel.exception listener <use-kernel-exception-event>`::

// src/EventListener/AccessDeniedListener.php
namespace App\EventListener;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;

class AccessDeniedListener implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [
// the priority must be greater than the Security HTTP
// ExceptionListener, to make sure it's called before
// the default exception listener
KernelEvents::EXCEPTION => ['onKernelException', 2],
];
}

public function onKernelException(ExceptionEvent $event): void
{
$exception = $event->getException();
if (!$exception instanceof AccessDeniedException) {
return;
}

// ... perform some action (e.g. logging)

// optionally set the custom response
$event->setResponse(new Response(null, 403));

// or stop propagation (prevents the next exception listeners from being called)
//$event->stopPropagation();
}
}

[8]ページ先頭

©2009-2025 Movatter.jp