diff --git a/security.rst b/security.rst index e3db5a33535..b32a64a865d 100644 --- a/security.rst +++ b/security.rst @@ -16,7 +16,7 @@ sections: #. Installing security support; -#. Initial ``security.yml`` setup (*authentication*); +#. Initial ``security.yaml`` setup (*authentication*); #. Denying access to your app (*authorization*); @@ -38,34 +38,32 @@ install the security feature before using it: .. _security-firewalls: .. _firewalls-authentication: +.. _initial-security-yml-setup-authentication: -1) Initial security.yml Setup (Authentication) ----------------------------------------------- +1) Initial security.yaml Setup (Authentication) +----------------------------------------------- -The security system is configured in ``app/config/security.yml``. The default -configuration looks like this: +The security system is configured in ``config/packages/security.yaml``. The +default configuration looks like this: .. configuration-block:: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: providers: - in_memory: - memory: ~ - + in_memory: { memory: ~ } firewalls: dev: pattern: ^/(_(profiler|wdt)|css|images|js)/ security: false - main: anonymous: ~ .. code-block:: xml - + loadFromExtension('security', array( 'providers' => array( 'in_memory' => array( @@ -150,7 +148,7 @@ To activate this, add the ``http_basic`` key under your firewall: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... @@ -162,7 +160,7 @@ To activate this, add the ``http_basic`` key under your firewall: .. code-block:: xml - + loadFromExtension('security', array( // ... 'firewalls' => array( @@ -210,20 +208,20 @@ example, if you use annotations, create something like this:: /** * @Route("/admin") */ - public function adminAction() + public function admin() { return new Response('Admin page!'); } } -Next, add an ``access_control`` entry to ``security.yml`` that requires the +Next, add an ``access_control`` entry to ``security.yaml`` that requires the user to be logged in to access this URL: .. configuration-block:: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... firewalls: @@ -237,7 +235,7 @@ user to be logged in to access this URL: .. code-block:: xml - + loadFromExtension('security', array( // ... 'firewalls' => array( @@ -312,14 +310,14 @@ configuring it. Symfony has a built-in way to or you can :doc:`create your own user provider `. The easiest (but most limited) way, is to configure Symfony to load hardcoded -users directly from the ``security.yml`` file itself. This is called an "in memory" +users directly from the ``security.yaml`` file itself. This is called an "in memory" provider, but it's better to think of it as an "in configuration" provider: .. configuration-block:: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: providers: in_memory: @@ -335,7 +333,7 @@ provider, but it's better to think of it as an "in configuration" provider: .. code-block:: xml - + loadFromExtension('security', array( 'providers' => array( 'in_memory' => array( @@ -398,7 +396,7 @@ To fix this, add an ``encoders`` key: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... @@ -408,7 +406,7 @@ To fix this, add an ``encoders`` key: .. code-block:: xml - + loadFromExtension('security', array( // ... @@ -468,7 +466,7 @@ If you'd like to load your users via the Doctrine ORM, that's easy! See C) Encoding the User's Password ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Whether your users are stored in ``security.yml``, in a database or somewhere +Whether your users are stored in ``security.yaml``, in a database or somewhere else, you'll want to encode their passwords. The best algorithm to use is ``bcrypt``: @@ -476,7 +474,7 @@ else, you'll want to encode their passwords. The best algorithm to use is .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... @@ -487,7 +485,7 @@ else, you'll want to encode their passwords. The best algorithm to use is .. code-block:: xml - + loadFromExtension('security', array( // ... @@ -534,7 +532,7 @@ It will give you something like this: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... @@ -551,7 +549,7 @@ It will give you something like this: .. code-block:: xml - + loadFromExtension('security', array( // ... @@ -616,7 +614,7 @@ D) Configuration Done! ~~~~~~~~~~~~~~~~~~~~~~ Congratulations! You now have a working authentication system that uses HTTP -basic auth and loads users right from the ``security.yml`` file. +basic auth and loads users right from the ``security.yaml`` file. Your next steps depend on your setup: @@ -657,7 +655,7 @@ Roles ~~~~~ When a user logs in, they receive a set of roles (e.g. ``ROLE_ADMIN``). In -the example above, these are hardcoded into ``security.yml``. If you're +the example above, these are hardcoded into ``security.yaml``. If you're loading users from the database, these are probably stored on a column in your table. @@ -691,7 +689,7 @@ Add Code to Deny Access There are **two** ways to deny access to something: -#. :ref:`access_control in security.yml ` +#. :ref:`access_control in security.yaml ` allows you to protect URL patterns (e.g. ``/admin/*``). This is easy, but less flexible; @@ -710,7 +708,7 @@ URL pattern. You saw this earlier, where anything matching the regular expressio .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... @@ -725,7 +723,7 @@ URL pattern. You saw this earlier, where anything matching the regular expressio .. code-block:: xml - + loadFromExtension('security', array( // ... @@ -776,7 +774,7 @@ matches the URL. .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... @@ -786,7 +784,7 @@ matches the URL. .. code-block:: xml - + loadFromExtension('security', array( // ... @@ -839,20 +837,34 @@ You can easily deny access from inside a controller:: // ... - public function helloAction($name) + public function hello($name) { // The second parameter is used to specify on what object the role is tested. $this->denyAccessUnlessGranted('ROLE_ADMIN', null, 'Unable to access this page!'); - // Old way : - // if (false === $this->get('security.authorization_checker')->isGranted('ROLE_ADMIN')) { - // throw $this->createAccessDeniedException('Unable to access this page!'); - // } - // ... } -In both cases, a special +.. tip:: + + The ``denyAccessUnlessGranted()`` is a shortcut provided by the optional + :ref:`base controller provided by Symfony `. + It's equivalent to the following code:: + + use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface + use Symfony\Component\Security\Core\Exception\AccessDeniedException; + // ... + + public function hello($name, AuthorizationCheckerInterface $authChecker) + { + if (false === $authChecker->isGranted('ROLE_ADMIN')) { + throw new AccessDeniedException('Unable to access this page!'); + } + + // ... + } + +If access is not granted, a special :class:`Symfony\\Component\\Security\\Core\\Exception\\AccessDeniedException` is thrown, which ultimately triggers a 403 HTTP response inside Symfony. @@ -873,7 +885,7 @@ using annotations:: /** * @Security("has_role('ROLE_ADMIN')") */ - public function helloAction($name) + public function hello($name) { // ... } @@ -922,11 +934,9 @@ user is logged in (you don't care about roles), then you can use // ... - public function helloAction($name) + public function hello($name) { - if (!$this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) { - throw $this->createAccessDeniedException(); - } + $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY'); // ... } @@ -1000,14 +1010,13 @@ After authentication, the ``User`` object of the current user can be accessed via the ``security.token_storage`` service. From inside a controller, this will look like:: - use Symfony\Component\Security\Core\User\UserInterface; - - public function indexAction() + public function index() { $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY'); $user = $this->getUser(); - // or you can also type-hint a method argument with UserInterface: e.g. "UserInterface $user" + // or you can also type-hint a method argument with this class: + // Symfony\Component\Security\Core\User\UserInterface (e.g. "UserInterface $user") } .. tip:: @@ -1021,7 +1030,7 @@ if your User object has a ``getFirstName()`` method, you could use that:: use Symfony\Component\HttpFoundation\Response; // ... - public function indexAction() + public function index() { // ... @@ -1039,7 +1048,7 @@ this is a quirk. If you're not logged in, the user is technically the string :class:`Symfony\\Component\\Security\\Core\\User\\UserInterface\\UserInterface` and being logged-in is optional, you can allow a null value for the argument:: - public function indexAction(UserInterface $user = null) + public function index(UserInterface $user = null) { // $user is null when not logged-in or anon. } @@ -1049,13 +1058,11 @@ the User object, and use the ``isGranted()`` method (or :ref:`access_control `) to do this:: // yay! Use this to see if the user is logged in - if (!$this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) { - throw $this->createAccessDeniedException(); - } + $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY'); // boo :(. Never check for the User object to see if they're logged in if ($this->getUser()) { - + // ... } Retrieving the User in a Template @@ -1099,7 +1106,7 @@ the firewall can handle this automatically for you when you activate the .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... @@ -1112,7 +1119,7 @@ the firewall can handle this automatically for you when you activate the .. code-block:: xml - + loadFromExtension('security', array( // ... @@ -1203,7 +1210,7 @@ rules by creating a role hierarchy: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... @@ -1213,7 +1220,7 @@ rules by creating a role hierarchy: .. code-block:: xml - + loadFromExtension('security', array( // ... diff --git a/security/access_control.rst b/security/access_control.rst index 6377a8eed3c..de0e114bda9 100644 --- a/security/access_control.rst +++ b/security/access_control.rst @@ -33,7 +33,7 @@ Take the following ``access_control`` entries as an example: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... access_control: @@ -44,7 +44,7 @@ Take the following ``access_control`` entries as an example: .. code-block:: xml - + + + App\Security\AccessDeniedHandler diff --git a/security/api_key_authentication.rst b/security/api_key_authentication.rst index 897792c90e9..f0fabab6020 100644 --- a/security/api_key_authentication.rst +++ b/security/api_key_authentication.rst @@ -211,7 +211,7 @@ The ``$userProvider`` might look something like this:: Next, make sure this class is registered as a service. If you're using the :ref:`default services.yaml configuration `, that happens automatically. A little later, you'll reference this service in -your :ref:`security.yml configuration `. +your :ref:`security.yaml configuration `. .. note:: @@ -292,7 +292,7 @@ and ``provider`` keys: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... @@ -310,7 +310,7 @@ and ``provider`` keys: .. code-block:: xml - + + + + loadFromExtension('framework', array( 'csrf_protection' => null, )); @@ -59,7 +59,7 @@ use the default provider available in the security component: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... @@ -72,7 +72,7 @@ use the default provider available in the security component: .. code-block:: xml - + + cachePool->getItem(md5($nonce)); - + // Validate that the nonce is *not* in cache // if it is, this could be a replay attack if ($cacheItem->isHit()) { throw new NonceExpiredException('Previously used nonce detected'); } - + // Store the item in cache for 5 minutes $cacheItem->set(null)->expiresAfter(300); $this->cachePool->save($cacheItem); diff --git a/security/custom_password_authenticator.rst b/security/custom_password_authenticator.rst index f44f0c0aedf..3817ebabc30 100644 --- a/security/custom_password_authenticator.rst +++ b/security/custom_password_authenticator.rst @@ -131,10 +131,10 @@ inside of it. Inside this method, the password encoder is needed to check the password's validity:: - $passwordValid = $this->encoder->isPasswordValid($user, $token->getCredentials()); + $passwordValid = $this->encoder->isPasswordValid($user, $token->getCredentials()); This is a service that is already available in Symfony and it uses the password algorithm -that is configured in the security configuration (e.g. ``security.yml``) under +that is configured in the security configuration (e.g. ``security.yaml``) under the ``encoders`` key. Below, you'll see how to inject that into the ``TimeAuthenticator``. .. _security-password-authenticator-config: @@ -153,7 +153,7 @@ using the ``simple_form`` key: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... @@ -168,7 +168,7 @@ using the ``simple_form`` key: .. code-block:: xml - + `, this happens automatically. -Modify ``security.yml`` ------------------------ +Modify ``security.yaml`` +------------------------ Everything comes together in your security configuration. Add the user provider -to the list of providers in the "security" section. Choose a name for the user provider +to the list of providers in the "security" config. Choose a name for the user provider (e.g. "webservice") and mention the ``id`` of the service you just defined. .. configuration-block:: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... @@ -195,7 +195,7 @@ to the list of providers in the "security" section. Choose a name for the user p .. code-block:: xml - + + + ` -#. :ref:`Configure security.yml to load from your entity ` +#. :ref:`Configure security.yaml to load from your entity ` Afterwards, you can learn more about :ref:`forbidding inactive users `, :ref:`using a custom query ` @@ -189,7 +189,7 @@ Want to know more? See :ref:`security-serialize-equatable`. ---------------------------------------------- Now that you have a ``User`` entity that implements ``UserInterface``, you -just need to tell Symfony's security system about it in ``security.yml``. +just need to tell Symfony's security system about it in ``security.yaml``. In this example, the user will enter their username and password via HTTP basic authentication. Symfony will query for a ``User`` entity matching @@ -452,7 +452,7 @@ interface only requires one method: ``loadUserByUsername($username)``:: :doc:`mapping definition of your entity `. To finish this, just remove the ``property`` key from the user provider in -``security.yml``: +``security.yaml``: .. configuration-block:: diff --git a/security/expressions.rst b/security/expressions.rst index e9ea4fdb6b8..13970159ecd 100644 --- a/security/expressions.rst +++ b/security/expressions.rst @@ -15,7 +15,7 @@ accepts an :class:`Symfony\\Component\\ExpressionLanguage\\Expression` object:: use Symfony\Component\ExpressionLanguage\Expression; // ... - public function indexAction() + public function index() { $this->denyAccessUnlessGranted(new Expression( '"ROLE_ADMIN" in roles or (user and user.isSuperAdmin())' @@ -70,17 +70,20 @@ Additionally, you have access to a number of functions inside the expression: The ``is_remember_me()`` and ``is_authenticated_fully()`` functions are *similar* to using ``IS_AUTHENTICATED_REMEMBERED`` and ``IS_AUTHENTICATED_FULLY`` with the ``isGranted()`` function - but they are **not** the same. The - following shows the difference:: + following controller snippet shows the difference:: use Symfony\Component\ExpressionLanguage\Expression; + use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; // ... - $ac = $this->get('security.authorization_checker'); - $access1 = $ac->isGranted('IS_AUTHENTICATED_REMEMBERED'); + public function index(AuthorizationCheckerInterface $auth) + { + $access1 = $auth->isGranted('IS_AUTHENTICATED_REMEMBERED'); - $access2 = $ac->isGranted(new Expression( - 'is_remember_me() or is_fully_authenticated()' - )); + $access2 = $auth->isGranted(new Expression( + 'is_remember_me() or is_fully_authenticated()' + )); + } Here, ``$access1`` and ``$access2`` will be the same value. Unlike the behavior of ``IS_AUTHENTICATED_REMEMBERED`` and ``IS_AUTHENTICATED_FULLY``, diff --git a/security/firewall_restriction.rst b/security/firewall_restriction.rst index 80e2bbc5212..6ca8203b4f6 100644 --- a/security/firewall_restriction.rst +++ b/security/firewall_restriction.rst @@ -5,25 +5,25 @@ How to Restrict Firewalls to a Specific Request =============================================== When using the Security component, you can create firewalls that match certain request options. -In most cases, matching against the URL is sufficient, but in special cases you can further +In most cases, matching against the URL is sufficient, but in special cases you can further restrict the initialization of a firewall against other options of the request. .. note:: - You can use any of these restrictions individually or mix them together to get - your desired firewall configuration. + You can use any of these restrictions individually or mix them together to get + your desired firewall configuration. Restricting by Pattern ---------------------- -This is the default restriction and restricts a firewall to only be initialized if the request URL -matches the configured ``pattern``. +This is the default restriction and restricts a firewall to only be initialized if the request URL +matches the configured ``pattern``. .. configuration-block:: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml # ... security: @@ -34,7 +34,7 @@ matches the configured ``pattern``. .. code-block:: xml - + + + + + + + + + + + - AppBundle:Security:login + App\Controller\SecurityController::login .. code-block:: php // config/routes.php + use App\Controller\SecurityController; use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; $collection = new RouteCollection(); $collection->add('login', new Route('/login', array( - '_controller' => 'AppBundle:Security:login', + '_controller' => array(SecurityController::class, 'login'), ))); return $collection; -Great! Next, add the logic to ``loginAction()`` that displays the login form:: +Great! Next, add the logic to ``login()`` that displays the login form:: // src/Controller/SecurityController.php use Symfony\Component\Security\Http\Authentication\AuthenticationUtils; - public function loginAction(Request $request, AuthenticationUtils $authUtils) + public function login(Request $request, AuthenticationUtils $authUtils) { // get the login error if there is one $error = $authUtils->getLastAuthenticationError(); @@ -230,7 +231,7 @@ Finally, create the template: The form can look like anything, but it usually follows some conventions: * The ``
`` element sends a ``POST`` request to the ``login`` route, since - that's what you configured under the ``form_login`` key in ``security.yml``; + that's what you configured under the ``form_login`` key in ``security.yaml``; * The username field has the name ``_username`` and the password field has the name ``_password``. @@ -300,7 +301,7 @@ all URLs (including the ``/login`` URL), will cause a redirect loop: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml # ... access_control: @@ -308,7 +309,7 @@ all URLs (including the ``/login`` URL), will cause a redirect loop: .. code-block:: xml - + + `, that happens automatically. -Finally, configure your ``firewalls`` key in ``security.yml`` to use this authenticator: +Finally, configure your ``firewalls`` key in ``security.yaml`` to use this authenticator: .. configuration-block:: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... @@ -283,7 +283,7 @@ Finally, configure your ``firewalls`` key in ``security.yml`` to use this authen .. code-block:: xml - + `. Then, type-hint ``CsrfTokenManagerInterface`` in your ``__construct()`` method -(or manually configure the ``security.csrf.token_manager`` service to be passed) -and add the following logic:: +(or manually configure the ``Symfony\Component\Security\Csrf\CsrfTokenManagerInterface`` +service to be passed) and add the following logic:: // src/Security/ExampleFormAuthenticator.php // ... diff --git a/security/impersonating_user.rst b/security/impersonating_user.rst index dad015da174..a952c284b6e 100644 --- a/security/impersonating_user.rst +++ b/security/impersonating_user.rst @@ -23,7 +23,7 @@ firewall listener: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... @@ -34,7 +34,7 @@ firewall listener: .. code-block:: xml - + get('security.authorization_checker'); - $tokenStorage = $this->get('security.token_storage'); + private $authChecker; + private $tokenStorage; - if ($authChecker->isGranted('ROLE_PREVIOUS_ADMIN')) { - foreach ($tokenStorage->getToken()->getRoles() as $role) { - if ($role instanceof SwitchUserRole) { - $impersonatorUser = $role->getSource()->getUser(); - break; + public function __construct(AuthorizationCheckerInterface $authChecker, TokenStorageInterface $tokenStorage) + { + $this->authChecker = $authChecker; + $this->tokenStorage = $tokenStorage; + } + + public function someMethod() + { + // ... + + if ($authChecker->isGranted('ROLE_PREVIOUS_ADMIN')) { + foreach ($tokenStorage->getToken()->getRoles() as $role) { + if ($role instanceof SwitchUserRole) { + $impersonatorUser = $role->getSource()->getUser(); + break; + } } } } @@ -129,7 +142,7 @@ setting: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... @@ -140,7 +153,7 @@ setting: .. code-block:: xml - + + - AppBundle:Security:login + App\Controller\SecurityController::login @@ -111,7 +111,7 @@ path: $collection = new RouteCollection(); $collection->add('login', new Route('/login', array( - '_controller' => 'AppBundle:Security:login', + '_controller' => 'App\Controller\SecurityController::login', ))); return $collection; @@ -151,7 +151,7 @@ The security configuration should be: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... @@ -165,7 +165,7 @@ The security configuration should be: .. code-block:: xml - + + loadFromExtension('security', array( @@ -326,7 +327,7 @@ Configuration example for form login .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... @@ -340,7 +341,7 @@ Configuration example for form login .. code-block:: xml - + loadFromExtension('security', array( @@ -380,7 +382,7 @@ Configuration example for HTTP Basic .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... @@ -394,7 +396,7 @@ Configuration example for HTTP Basic .. code-block:: xml - + loadFromExtension('security', array( @@ -433,7 +436,7 @@ Configuration example for form login and query_string .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... @@ -448,7 +451,7 @@ Configuration example for form login and query_string .. code-block:: xml - + + + + + + + + + id="App\Security\Encoder\MyCustomPasswordEncoder" /> .. code-block:: php // app/config/security.php + // ... + use App\Security\Encoder\MyCustomPasswordEncoder; + $container->loadFromExtension('security', array( // ... 'encoders' => array( 'app_encoder' => array( - 'id' => 'app.password_encoder_service' + 'id' => MyCustomPasswordEncoder::class ), ), )); -This creates an encoder named ``app_encoder`` from a service named -``app.password_encoder_service``. +This creates an encoder named ``app_encoder`` from a service with the ID +``App\Security\Encoder\MyCustomPasswordEncoder``. diff --git a/security/password_encoding.rst b/security/password_encoding.rst index 7ffceb57647..2a3c6509eb8 100644 --- a/security/password_encoding.rst +++ b/security/password_encoding.rst @@ -17,7 +17,7 @@ in the following way from a controller:: use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface; - public function registerAction(UserPasswordEncoderInterface $encoder) + public function register(UserPasswordEncoderInterface $encoder) { // whatever *your* User object is $user = new App\Entity\User(); @@ -29,7 +29,7 @@ in the following way from a controller:: In order for this to work, just make sure that you have the encoder for your user class (e.g. ``App\Entity\User``) configured under the ``encoders`` -key in ``config/security.yaml``. +key in ``config/packages/security.yaml``. The ``$encoder`` object also has an ``isPasswordValid()`` method, which takes the ``User`` object as the first argument and the plain password to check diff --git a/security/pre_authenticated.rst b/security/pre_authenticated.rst index 966b657d52d..883243e9c1b 100644 --- a/security/pre_authenticated.rst +++ b/security/pre_authenticated.rst @@ -32,7 +32,7 @@ Enable the x509 authentication for a particular firewall in the security configu .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... @@ -44,7 +44,7 @@ Enable the x509 authentication for a particular firewall in the security configu .. code-block:: xml - + + diff --git a/security/remember_me.rst b/security/remember_me.rst index 0a5ddcc471a..d964127a7d3 100644 --- a/security/remember_me.rst +++ b/security/remember_me.rst @@ -14,7 +14,7 @@ the session lasts using a cookie with the ``remember_me`` firewall option: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... @@ -32,7 +32,7 @@ the session lasts using a cookie with the ``remember_me`` firewall option: .. code-block:: xml - + denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY'); @@ -261,7 +261,7 @@ your controller using annotations: /** * @Security("is_granted('IS_AUTHENTICATED_FULLY')") */ - public function editAction($name) + public function edit($name) { // ... } @@ -278,12 +278,12 @@ your controller using annotations: * Once the user has entered their username and password, assuming the user receives the ``ROLE_USER`` role per your configuration, the user will have the ``IS_AUTHENTICATED_FULLY`` role and be able to access - any page in the account section, including the ``editAction()`` controller. + any page in the account section, including the ``edit()`` controller. * If the user's session ends, when the user returns to the site, they will be able to access every account page - except for the edit page - without being forced to re-authenticate. However, when they try to access the - ``editAction()`` controller, they will be forced to re-authenticate, since + ``edit()`` controller, they will be forced to re-authenticate, since they are not, yet, fully authenticated. For more information on securing services or methods in this way, diff --git a/security/securing_services.rst b/security/securing_services.rst index 56b53420629..0b24092a7d6 100644 --- a/security/securing_services.rst +++ b/security/securing_services.rst @@ -7,20 +7,23 @@ How to Secure any Service or Method in your Application In the security article, you can see how to :ref:`secure a controller ` by requesting -the ``security.authorization_checker`` service from the Service Container and -checking the current user's role:: +the ``Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface`` +service from the Service Container and checking the current user's role:: // ... + use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; use Symfony\Component\Security\Core\Exception\AccessDeniedException; - public function helloAction($name) + public function hello(AuthorizationCheckerInterface $authChecker) { - $this->denyAccessUnlessGranted('ROLE_ADMIN'); + if (!$authChecker->isGranted('ROLE_ADMIN')) { + throw new AccessDeniedException(); + } // ... } -You can also secure *any* service by injecting the ``security.authorization_checker`` +You can also secure *any* service by injecting the authorization checker service into it. For a general introduction to injecting dependencies into services see the :doc:`/service_container` article. For example, suppose you have a ``NewsletterManager`` class that sends out emails and you want to @@ -41,7 +44,8 @@ Before you add security, the class looks something like this:: } Your goal is to check the user's role when the ``sendNewsletter()`` method is -called. The first step towards this is to inject the ``security.authorization_checker`` +called. The first step towards this is to inject the +``Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface`` service into the object:: // src/Newsletter/NewsletterManager.php @@ -52,16 +56,16 @@ service into the object:: class NewsletterManager { - protected $authorizationChecker; + protected $authChecker; - public function __construct(AuthorizationCheckerInterface $authorizationChecker) + public function __construct(AuthorizationCheckerInterface $authChecker) { - $this->authorizationChecker = $authorizationChecker; + $this->authChecker = $authChecker; } public function sendNewsletter() { - if (!$this->authorizationChecker->isGranted('ROLE_NEWSLETTER_ADMIN')) { + if (!$this->authChecker->isGranted('ROLE_NEWSLETTER_ADMIN')) { throw new AccessDeniedException(); } @@ -72,7 +76,7 @@ service into the object:: } If you're using the :ref:`default services.yaml configuration `, -Symfony will automatically pass the ``security.authorization_checker`` to your service +Symfony will automatically pass the authorization checker to your service thanks to autowiring and the ``AuthorizationCheckerInterface`` type-hint. If the current user does not have the ``ROLE_NEWSLETTER_ADMIN``, they will diff --git a/security/security_checker.rst b/security/security_checker.rst index 0316c1bd7ec..d77552fd70b 100644 --- a/security/security_checker.rst +++ b/security/security_checker.rst @@ -5,9 +5,17 @@ How to Check for Known Security Vulnerabilities in Your Dependencies ==================================================================== When using lots of dependencies in your Symfony projects, some of them may -contain security vulnerabilities. That's why Symfony includes a command called +contain security vulnerabilities. That's why Symfony provides a command called ``security:check`` that checks your ``composer.lock`` file to find any known -security vulnerability in your installed dependencies: +security vulnerability in your installed dependencies. + +First, install the security checker in your project: + +.. code-block:: terminal + + $ composer require security-checker + +Then run this command: .. code-block:: terminal @@ -24,10 +32,4 @@ FriendsOfPHP organization. any of your dependencies is affected by a known security vulnerability. Therefore, you can easily integrate it in your build process. -.. note:: - - To enable the ``security:check`` command, make sure the - `SensioDistributionBundle`_ is installed and enabled in your application. - .. _`security advisories database`: https://github.com/FriendsOfPHP/security-advisories -.. _`SensioDistributionBundle`: https://github.com/sensiolabs/SensioDistributionBundle diff --git a/security/user_checkers.rst b/security/user_checkers.rst index 2a40d64fab3..9287a9c51dd 100644 --- a/security/user_checkers.rst +++ b/security/user_checkers.rst @@ -69,7 +69,7 @@ is the service id of your user checker: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml # ... security: @@ -81,7 +81,7 @@ is the service id of your user checker: .. code-block:: xml - + +