From 9c4b9fe35816a7a982ccefc246a5616efb0f4be8 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Wed, 22 Nov 2017 19:41:14 +0100 Subject: [PATCH 1/4] (WIP) Updated security/* articles to Symfony 4 --- security/access_control.rst | 8 ++++---- security/access_denied_handler.rst | 2 +- security/api_key_authentication.rst | 6 +++--- security/csrf_in_login_form.rst | 4 ++-- security/custom_password_authenticator.rst | 2 +- security/custom_provider.rst | 8 ++++---- security/firewall_restriction.rst | 24 +++++++++++----------- security/force_https.rst | 4 ++-- security/form_login.rst | 10 ++++----- security/form_login_setup.rst | 6 +++--- security/guard_authentication.rst | 2 +- security/impersonating_user.rst | 4 ++-- security/json_login_setup.rst | 4 ++-- security/ldap.rst | 8 ++++---- security/multiple_guard_authenticators.rst | 4 ++-- security/multiple_user_providers.rst | 4 ++-- security/named_encoders.rst | 6 +++--- security/pre_authenticated.rst | 4 ++-- security/remember_me.rst | 2 +- security/user_checkers.rst | 2 +- security/voters.rst | 2 +- 21 files changed, 58 insertions(+), 58 deletions(-) diff --git a/security/access_control.rst b/security/access_control.rst index 6377a8eed3c..16ab831a78b 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: @@ -171,7 +171,7 @@ pattern so that it is only accessible by requests from the local server itself: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... access_control: @@ -252,7 +252,7 @@ key: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... access_control: @@ -300,7 +300,7 @@ the user will be redirected to ``https``: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... access_control: diff --git a/security/access_denied_handler.rst b/security/access_denied_handler.rst index 3e912bd73e0..72278602ff2 100644 --- a/security/access_denied_handler.rst +++ b/security/access_denied_handler.rst @@ -38,7 +38,7 @@ configure it under your firewall: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml firewalls: # ... diff --git a/security/api_key_authentication.rst b/security/api_key_authentication.rst index 897792c90e9..36c3e6dd5de 100644 --- a/security/api_key_authentication.rst +++ b/security/api_key_authentication.rst @@ -292,7 +292,7 @@ and ``provider`` keys: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... @@ -364,7 +364,7 @@ If you have defined ``access_control``, make sure to add a new entry: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... @@ -423,7 +423,7 @@ configuration or set it to ``false``: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... diff --git a/security/csrf_in_login_form.rst b/security/csrf_in_login_form.rst index 79230f10062..39ea8c46351 100644 --- a/security/csrf_in_login_form.rst +++ b/security/csrf_in_login_form.rst @@ -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: # ... @@ -171,7 +171,7 @@ After this, you have protected your login form against CSRF attacks. .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... diff --git a/security/custom_password_authenticator.rst b/security/custom_password_authenticator.rst index f44f0c0aedf..abc622f0499 100644 --- a/security/custom_password_authenticator.rst +++ b/security/custom_password_authenticator.rst @@ -153,7 +153,7 @@ using the ``simple_form`` key: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... diff --git a/security/custom_provider.rst b/security/custom_provider.rst index ce471820ecf..1145e109943 100644 --- a/security/custom_provider.rst +++ b/security/custom_provider.rst @@ -9,7 +9,7 @@ When a user submits a username and password, the authentication layer asks the configured user provider to return a user object for a given username. Symfony then checks whether the password of this user is correct and generates a security token so the user stays authenticated during the current session. -Out of the box, Symfony has four user providers: ``memory``, ``entity``, +Out of the box, Symfony has four user providers: ``memory``, ``entity``, ``ldap`` and ``chain``. In this entry you'll see how you can create your own user provider, which could be useful if your users are accessed via a custom database, a file, or - as shown in this example - a web service. @@ -185,7 +185,7 @@ to the list of providers in the "security" section. Choose a name for the user p .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... @@ -233,7 +233,7 @@ users, e.g. by filling in a login form. You can do this by adding a line to the .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... @@ -301,7 +301,7 @@ is compared to the hashed password returned by your ``getPassword()`` method. .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... diff --git a/security/firewall_restriction.rst b/security/firewall_restriction.rst index 80e2bbc5212..36cf40fa48b 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: @@ -64,23 +64,23 @@ matches the configured ``pattern``. ), )); -The ``pattern`` is a regular expression. In this example, the firewall will only be +The ``pattern`` is a regular expression. In this example, the firewall will only be activated if the URL starts (due to the ``^`` regex character) with ``/admin``. If -the URL does not match this pattern, the firewall will not be activated and subsequent +the URL does not match this pattern, the firewall will not be activated and subsequent firewalls will have the opportunity to be matched for this request. Restricting by Host ------------------- -If matching against the ``pattern`` only is not enough, the request can also be matched against -``host``. When the configuration option ``host`` is set, the firewall will be restricted to +If matching against the ``pattern`` only is not enough, the request can also be matched against +``host``. When the configuration option ``host`` is set, the firewall will be restricted to only initialize if the host from the request matches against the configuration. .. configuration-block:: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml # ... security: @@ -138,7 +138,7 @@ the provided HTTP methods. .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml # ... security: diff --git a/security/force_https.rst b/security/force_https.rst index f06136a5255..b8e0c5bdaf8 100644 --- a/security/force_https.rst +++ b/security/force_https.rst @@ -13,7 +13,7 @@ to use HTTPS then you could use the following configuration: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... @@ -61,7 +61,7 @@ role: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... diff --git a/security/form_login.rst b/security/form_login.rst index b436e89054b..9a8d685740a 100644 --- a/security/form_login.rst +++ b/security/form_login.rst @@ -42,7 +42,7 @@ a relative/absolute URL or a Symfony route name: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... @@ -99,7 +99,7 @@ previously requested URL and always redirect to the default page: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... @@ -198,7 +198,7 @@ parameter is included in the request, you may use the value of the .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... @@ -264,7 +264,7 @@ option to define a new target via a relative/absolute URL or a Symfony route nam .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... @@ -351,7 +351,7 @@ redirects can be customized using the ``target_path_parameter`` and .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... diff --git a/security/form_login_setup.rst b/security/form_login_setup.rst index cabea4f4179..3d8d9c47b9f 100644 --- a/security/form_login_setup.rst +++ b/security/form_login_setup.rst @@ -18,7 +18,7 @@ First, enable form login under your firewall: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... @@ -300,7 +300,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: @@ -338,7 +338,7 @@ fixes the problem: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml # ... access_control: diff --git a/security/guard_authentication.rst b/security/guard_authentication.rst index 5cb50da2463..b8aca32129b 100644 --- a/security/guard_authentication.rst +++ b/security/guard_authentication.rst @@ -260,7 +260,7 @@ Finally, configure your ``firewalls`` key in ``security.yml`` to use this authen .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... diff --git a/security/impersonating_user.rst b/security/impersonating_user.rst index dad015da174..4d12591fa46 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: # ... @@ -129,7 +129,7 @@ setting: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... diff --git a/security/json_login_setup.rst b/security/json_login_setup.rst index d6f9debc1ff..8b5b0f9b182 100644 --- a/security/json_login_setup.rst +++ b/security/json_login_setup.rst @@ -11,7 +11,7 @@ First, enable the JSON login under your firewall: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... @@ -151,7 +151,7 @@ The security configuration should be: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... diff --git a/security/ldap.rst b/security/ldap.rst index 42195fd6b4d..3814b78f36f 100644 --- a/security/ldap.rst +++ b/security/ldap.rst @@ -127,7 +127,7 @@ use the ``ldap`` user provider. .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... @@ -326,7 +326,7 @@ Configuration example for form login .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... @@ -380,7 +380,7 @@ Configuration example for HTTP Basic .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... @@ -433,7 +433,7 @@ Configuration example for form login and query_string .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... diff --git a/security/multiple_guard_authenticators.rst b/security/multiple_guard_authenticators.rst index 778fc24d75f..1b7a3d4dec8 100644 --- a/security/multiple_guard_authenticators.rst +++ b/security/multiple_guard_authenticators.rst @@ -22,7 +22,7 @@ This is how your security configuration can look in action: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... firewalls: @@ -93,7 +93,7 @@ the solution is to split the configuration into two separate firewalls: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... firewalls: diff --git a/security/multiple_user_providers.rst b/security/multiple_user_providers.rst index 2643654ad4a..1de0c7be8b9 100644 --- a/security/multiple_user_providers.rst +++ b/security/multiple_user_providers.rst @@ -10,7 +10,7 @@ creating a new provider that chains the two together: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: providers: chain_provider: @@ -92,7 +92,7 @@ to use a specific provider: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: firewalls: secured_area: diff --git a/security/named_encoders.rst b/security/named_encoders.rst index 0ed0b696c29..b019cdc5c11 100644 --- a/security/named_encoders.rst +++ b/security/named_encoders.rst @@ -11,7 +11,7 @@ to apply to all instances of a specific class: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... encoders: @@ -61,7 +61,7 @@ named encoders: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... encoders: @@ -133,7 +133,7 @@ you must register a service for it in order to use it as a named encoder: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: # ... encoders: diff --git a/security/pre_authenticated.rst b/security/pre_authenticated.rst index 966b657d52d..6e036018257 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: # ... @@ -111,7 +111,7 @@ corresponding firewall in your security configuration: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: firewalls: secured_area: diff --git a/security/remember_me.rst b/security/remember_me.rst index 0a5ddcc471a..16db931be27 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: # ... diff --git a/security/user_checkers.rst b/security/user_checkers.rst index 2a40d64fab3..701568bd802 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: diff --git a/security/voters.rst b/security/voters.rst index c253aed2402..ec63062c93f 100644 --- a/security/voters.rst +++ b/security/voters.rst @@ -289,7 +289,7 @@ security configuration: .. code-block:: yaml - # app/config/security.yml + # config/packages/security.yaml security: access_decision_manager: strategy: unanimous From a668558795b9d3b8cc08479e36a0c1c1683189d1 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Wed, 22 Nov 2017 20:51:06 +0100 Subject: [PATCH 2/4] Updated security/* articles to Symfony 4 --- security/access_control.rst | 6 ++-- security/access_denied_handler.rst | 1 + security/api_key_authentication.rst | 8 +++--- security/csrf_in_login_form.rst | 12 ++++---- security/custom_authentication_provider.rst | 4 +-- security/custom_password_authenticator.rst | 6 ++-- security/custom_provider.rst | 14 +++++----- security/entity_provider.rst | 4 +-- security/expressions.rst | 17 ++++++----- security/firewall_restriction.rst | 6 ++-- security/force_https.rst | 4 +-- security/form_login.rst | 10 +++---- security/form_login_setup.rst | 21 +++++++------- security/guard_authentication.rst | 8 +++--- security/impersonating_user.rst | 31 +++++++++++++++------ security/json_login_setup.rst | 14 +++++----- security/ldap.rst | 11 +++++--- security/multiple_guard_authenticators.rst | 4 +-- security/multiple_user_providers.rst | 4 +-- security/named_encoders.rst | 19 +++++++------ security/password_encoding.rst | 4 +-- security/pre_authenticated.rst | 4 +-- security/remember_me.rst | 10 +++---- security/securing_services.rst | 26 +++++++++-------- security/security_checker.rst | 18 ++++++------ security/user_checkers.rst | 2 +- security/voters.rst | 8 +++--- 27 files changed, 153 insertions(+), 123 deletions(-) diff --git a/security/access_control.rst b/security/access_control.rst index 16ab831a78b..de0e114bda9 100644 --- a/security/access_control.rst +++ b/security/access_control.rst @@ -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 36c3e6dd5de..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:: @@ -310,7 +310,7 @@ and ``provider`` keys: .. code-block:: xml - + + + + loadFromExtension('framework', array( 'csrf_protection' => null, )); @@ -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 abc622f0499..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: @@ -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:: @@ -195,7 +195,7 @@ to the list of providers in the "security" section. Choose a name for the user p .. code-block:: xml - + + + `. 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 36cf40fa48b..6ca8203b4f6 100644 --- a/security/firewall_restriction.rst +++ b/security/firewall_restriction.rst @@ -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(); @@ -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:: @@ -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 4d12591fa46..a952c284b6e 100644 --- a/security/impersonating_user.rst +++ b/security/impersonating_user.rst @@ -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; + } } } } @@ -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; @@ -165,7 +165,7 @@ The security configuration should be: .. code-block:: xml - + + loadFromExtension('security', array( @@ -340,7 +341,7 @@ Configuration example for form login .. code-block:: xml - + loadFromExtension('security', array( @@ -394,7 +396,7 @@ Configuration example for HTTP Basic .. code-block:: xml - + loadFromExtension('security', array( @@ -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 6e036018257..883243e9c1b 100644 --- a/security/pre_authenticated.rst +++ b/security/pre_authenticated.rst @@ -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 16db931be27..d964127a7d3 100644 --- a/security/remember_me.rst +++ b/security/remember_me.rst @@ -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 701568bd802..9287a9c51dd 100644 --- a/security/user_checkers.rst +++ b/security/user_checkers.rst @@ -81,7 +81,7 @@ is the service id of your user checker: .. code-block:: xml - + + Date: Fri, 24 Nov 2017 12:01:10 +0100 Subject: [PATCH 3/4] Updated the main security article --- security.rst | 149 +++++++++++++++++++++++++++------------------------ 1 file changed, 78 insertions(+), 71 deletions(-) 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( // ... From c40a9d9201e7c73693ffab88077821c91e2a9748 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Fri, 24 Nov 2017 15:51:03 +0100 Subject: [PATCH 4/4] Fixed the last references to security.yml --- security/entity_provider.rst | 2 +- security/form_login_setup.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/security/entity_provider.rst b/security/entity_provider.rst index f78d62c9ed0..bed6a01a7c3 100644 --- a/security/entity_provider.rst +++ b/security/entity_provider.rst @@ -24,7 +24,7 @@ Introduction Loading users via a Doctrine entity has 2 basic steps: #. :ref:`Create your User entity ` -#. :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 ` diff --git a/security/form_login_setup.rst b/security/form_login_setup.rst index 2534ce34bf1..78db3a9f4ff 100644 --- a/security/form_login_setup.rst +++ b/security/form_login_setup.rst @@ -231,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``.