Skip to content

Commit d6f676a

Browse files
committed
minor symfony#16034 [Security] Document custom access decision managers (derrabus)
This PR was merged into the 5.4 branch. Discussion ---------- [Security] Document custom access decision managers Fixes symfony#16032 Documents symfony/symfony#42177 Commits ------- 04ce795 Document custom access decision managers
2 parents 935fed8 + 04ce795 commit d6f676a

File tree

2 files changed

+109
-34
lines changed

2 files changed

+109
-34
lines changed

components/security/authorization.rst

Lines changed: 57 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -37,26 +37,8 @@ Access Decision Manager
3737
Since deciding whether or not a user is authorized to perform a certain
3838
action can be a complicated process, the standard :class:`Symfony\\Component\\Security\\Core\\Authorization\\AccessDecisionManager`
3939
itself depends on multiple voters, and makes a final verdict based on all
40-
the votes (either positive, negative or neutral) it has received. It
41-
recognizes several strategies:
42-
43-
``affirmative`` (default)
44-
grant access as soon as there is one voter granting access;
45-
46-
``consensus``
47-
grant access if there are more voters granting access than there are denying;
48-
49-
``unanimous``
50-
only grant access if none of the voters has denied access. If all voters
51-
abstained from voting, the decision is based on the ``allow_if_all_abstain``
52-
config option (which defaults to ``false``).
53-
54-
``priority``
55-
grants or denies access by the first voter that does not abstain;
56-
57-
.. versionadded:: 5.1
58-
59-
The ``priority`` version strategy was introduced in Symfony 5.1.
40+
the votes (either positive, negative or neutral) it has received and the
41+
given strategy.
6042

6143
Usage of the available options in detail::
6244

@@ -65,27 +47,69 @@ Usage of the available options in detail::
6547
// instances of Symfony\Component\Security\Core\Authorization\Voter\VoterInterface
6648
$voters = [...];
6749

68-
// one of "affirmative", "consensus", "unanimous", "priority"
50+
// instance of Symfony\Component\Security\Core\Authorization\Strategy\AccessDecisionStrategyInterface
6951
$strategy = ...;
7052

71-
// whether or not to grant access when all voters abstain
72-
$allowIfAllAbstainDecisions = ...;
73-
74-
// whether or not to grant access when there is no majority (applies only to the "consensus" strategy)
75-
$allowIfEqualGrantedDeniedDecisions = ...;
76-
77-
$accessDecisionManager = new AccessDecisionManager(
78-
$voters,
79-
$strategy,
80-
$allowIfAllAbstainDecisions,
81-
$allowIfEqualGrantedDeniedDecisions
82-
);
53+
$accessDecisionManager = new AccessDecisionManager($voters, $strategy);
8354

8455
.. seealso::
8556

8657
You can change the default strategy in the
8758
:ref:`configuration <security-voters-change-strategy>`.
8859

60+
Strategies
61+
----------
62+
63+
.. versionadded:: 5.4
64+
65+
The strategy classes were introduced in Symfony 5.4. In earlier versions, the strategy was passed as a string.
66+
67+
The following strategies are bundled with the component:
68+
69+
``AffirmativeStrategy`` (default)
70+
grant access as soon as there is one voter granting access;
71+
72+
``ConsensusStrategy``
73+
grant access if there are more voters granting access than there are denying;
74+
if there is a draw between votes, the decision is made based on the
75+
``$allowIfEqualGrantedDeniedDecisions`` constructor parameter which defaults to ``true``.
76+
77+
``UnanimousStrategy``
78+
only grant access if none of the voters has denied access.
79+
80+
``PriorityStrategy``
81+
grants or denies access by the first voter that does not abstain;
82+
83+
.. versionadded:: 5.1
84+
85+
The "priority" version strategy was introduced in Symfony 5.1.
86+
87+
If all voters abstained from voting, the decision is based on the ``$allowIfAllAbstainDecisions``
88+
constructor parameter which is supported by all of the built-in strategies and defaults to ``false``.
89+
90+
If none of the built-in strategies seem to fit, a custom strategy may be provided. The strategy will
91+
receive a stream of votes and may return as soon as it has seen enough votes to come to a conclusion.
92+
93+
::
94+
95+
/**
96+
* Always picks the third voter.
97+
*/
98+
class ThirdVoterStrategy implements AccessDecisionStrategyInterface
99+
{
100+
public function decide(\Traversable $results): bool
101+
{
102+
$votes = 0;
103+
foreach ($results as $result) {
104+
if (++$votes === 3) {
105+
return $result === VoterInterface::ACCESS_GRANTED;
106+
}
107+
}
108+
109+
return false;
110+
}
111+
}
112+
89113
Voters
90114
------
91115

security/voters.rst

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,58 @@ security configuration:
345345
Custom Access Decision Strategy
346346
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
347347

348-
If none of the built-in strategies fits your use case, define the ``service``
348+
.. versionadded:: 5.4
349+
350+
The ``strategy_service`` option was introduced in Symfony 5.4.
351+
352+
If none of the built-in strategies fits your use case, define the ``strategy_service``
353+
option to use a custom service (your service must implement the
354+
:class:`Symfony\\Component\\Security\\Core\Authorization\\Strategy\\AccessDecisionStrategyInterface`):
355+
356+
.. configuration-block::
357+
358+
.. code-block:: yaml
359+
360+
# config/packages/security.yaml
361+
security:
362+
access_decision_manager:
363+
strategy_service: App\Security\MyCustomAccessDecisionStrategy
364+
# ...
365+
366+
.. code-block:: xml
367+
368+
<!-- config/packages/security.xml -->
369+
<?xml version="1.0" encoding="UTF-8" ?>
370+
<srv:container xmlns="http://symfony.com/schema/dic/security"
371+
xmlns:srv="http://symfony.com/schema/dic/services"
372+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
373+
xsi:schemaLocation="http://symfony.com/schema/dic/services
374+
https://symfony.com/schema/dic/services/services-1.0.xsd"
375+
>
376+
377+
<config>
378+
<access-decision-manager
379+
strategy-service="App\Security\MyCustomAccessDecisionStrategy"/>
380+
</config>
381+
</srv:container>
382+
383+
.. code-block:: php
384+
385+
// config/packages/security.php
386+
use App\Security\MyCustomAccessDecisionStrategy;
387+
use Symfony\Config\SecurityConfig;
388+
389+
return static function (SecurityConfig $security) {
390+
$security->accessDecisionManager()
391+
->strategyService(MyCustomAccessDecisionStrategy::class)
392+
// ...
393+
;
394+
};
395+
396+
Custom Access Decision Manager
397+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
398+
399+
If you need to provide an entirely custom access decision manager, define the ``service``
349400
option to use a custom service as the Access Decision Manager (your service
350401
must implement the :class:`Symfony\\Component\\Security\\Core\\Authorization\\AccessDecisionManagerInterface`):
351402

0 commit comments

Comments
 (0)