Sécurité


Le système de sécurité de Symfony est très puissant, mais il peut aussi prêter à confusion lors de sa configuration. Dans ce grand chapitre, vous apprendrez étape par étape comment mettre en place la sécurité de votre application, depuis la configuration du pare-feu (firewall) et le chargement des utilisateurs, jusqu'au refus d'accès et à l'obtention des objets utilisateur. En fonction de vos besoins, la configuration initiale peut parfois être pénible. Cependant, une fois terminé, le système de sécurité de Symfony est à la fois flexible et (espérons-le) amusant à utiliser.

Comme il y a beaucoup à dire, ce chapitre est organisé en plusieurs grands chapitres :

  1. Initialisation des paramètres de security.yml (security.yml 的设置 (authentication/验证 );

  2. 拒绝访问你的程序 (authorization/授权 );

  3. 获取当前的User对象;

它们被细分为许多小块内容(但仍然令人着迷),像是 logging out加密用户密码

1)初始化security.yml的设置 (Authentication/验证) 

security系统在 app/config/security.yml 中进行配置。默认的配置是这样的:

PHP:// app/config/security.php$container->loadFromExtension('security', array(
    'providers' => array(
        'in_memory' => array(
            'memory' => null,
        ),
    ),
    'firewalls' => array(
        'dev' => array(
            'pattern'    => '^/(_(profiler|wdt)|css|images|js)/',
            'security'   => false,
        ),
        'default' => array(
            'anonymous'  => null,
        ),
    ),));
XML:<!-- app/config/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        http://Symfony.com/schema/dic/services/services-1.0.xsd">     <config>
        <provider name="in_memory">
            <memory />
        </provider>         <firewall name="dev"            pattern="^/(_(profiler|wdt)|css|images|js)/"            security="false" />         <firewall name="default">
            <anonymous />
        </firewall>
    </config></srv:container>
YAML:# app/config/security.ymlsecurity:
    providers:
        in_memory:
            memory: ~
    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        default:
            anonymous: ~

firewalls 键是security配置的 核心dev 防火墙并不重要,它只是确保Symfony开发工具 - 也就是居于 /_profiler/_wdt 之下的那些URL将不会被你的security所阻止。

你也可以针对请求中的其他细节来匹配一个请求(如 host主机)。阅读 如何把防火墙限制在特定请求 以了解更多内容和例程。

所有其他的URL将被 default 防火墙中处理(没有 pattern 键意味着它可以匹配所有 URL)。你可以认为防火墙就是你的security系统,因此通常只有一个主力防火墙就变得有意义了。但这并 意味着每一个URL都需要验证 - anonymous 键可以搞定这个。事实上,如果你现在去首页,是可以访问的,并将看到你以 anon.authentification/vérification

) ; 11.png

Refuser l'accès à votre programme (

autorisation/autorisation

) ;

Obtenir l'objet utilisateur actuel Ils sont décomposés en plusieurs petits morceaux (mais toujours déroutants) Les gens sont fascinés), comme la se déconnecter et le crypter les mots de passe des utilisateurs.

1) Initialiser les paramètres security.yml (Authentification/vérification)

système de sécurité dans app Configurer dans /config/security.yml. La configuration par défaut est la suivante : la clé 🎜
PHP:// app/config/security.php$container->loadFromExtension('security', array(
    // ...
    'firewalls' => array(
        // ...
        'default' => array(
            'anonymous'  => null,
            'http_basic' => null,
        ),
    ),));
XML:<!-- app/config/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        http://Symfony.com/schema/dic/services/services-1.0.xsd">     <config>
        <!-- ... -->         <firewall name="default">
            <anonymous />
            <http-basic />
        </firewall>
    </config></srv:container>
YAML:# app/config/security.ymlsecurity:    # ...
    firewalls:        # ...
        default:
            anonymous: ~
            http_basic: ~
🎜firewalls est la configuration de sécurité 🎜core🎜. Le pare-feu dev n'est pas important, il garantit simplement que les outils de développement Symfony - c'est-à-dire les URL sous /_profiler et /_wdt ne le seront pas. Bloqué par votre sécurité. 🎜🎜🎜🎜Vous pouvez également faire correspondre une demande avec d'autres détails dans la demande (comme l'hôte). Lisez
Comment restreindre le pare-feu à des demandes spécifiques🎜 pour plus d'informations et d'exemples. 🎜🎜🎜🎜Toutes les autres URL seront gérées par le pare-feu default (l'absence de clé pattern signifie qu'elle peut correspondre à 🎜toutes les 🎜 URL). Vous pouvez considérer le pare-feu comme votre système de sécurité. Il est donc généralement judicieux de n’avoir qu’un seul pare-feu principal. Mais cela ne signifie pas 🎜🎜 que chaque URL doit être vérifiée - la clé anonyme s'en charge. En fait, si vous allez sur la page d'accueil maintenant, vous y aurez accès et verrez que vous êtes "vérifié" en tant que anon.. Ne vous laissez pas berner par le « Oui » à côté de Authentifié, vous n'êtes toujours qu'un utilisateur anonyme : 🎜🎜🎜🎜🎜 Plus tard, vous apprendrez comment refuser l'accès à une URL ou à un contrôleur spécifique (action qu'elle contient). 🎜🎜🎜🎜La sécurité est 🎜hautement🎜 configurable et toutes les options de configuration sont présentées dans le 🎜Référence de configuration de sécurité🎜, avec quelques instructions supplémentaires. 🎜🎜🎜

A) Configurez "comment autoriser les utilisateurs à s'authentifier"

La tâche principale du pare-feu est de configurer comment autoriser vos utilisateurs à s'authentifier. Est-ce qu'ils ont besoin d'un formulaire de connexion ? Ou une authentification de base HTTP ? Ou un jeton API ? Ou tout ce qui précède ?

Commençons par l'authentification de base HTTP (l'ancienne popup). Pour activer cette fonctionnalité, ajoutez http_basic au pare-feu : http_basic 到firewall下面:

// src/AppBundle/Controller/DefaultController.php
// ... use 
Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;use Symfony\Bundle\FrameworkBundle\Controller\Controller;use Symfony\Component\HttpFoundation\Response; class DefaultController extends Controller{
   /**
     * @Route("/admin")
     */
    public function adminAction()
    {
        return new Response('<html><body>Admin page!</body></html>');
    }}
PHP:// app/config/security.php$container->loadFromExtension('security', array(
    // ...
    'firewalls' => array(
        // ...
        'default' => array(
            // ...
        ),
    ),
   'access_control' => array(
       // require ROLE_ADMIN for /admin*
        array('path' => '^/admin', 'role' => 'ROLE_ADMIN'),
    ),));
XML:<!-- app/config/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        http://Symfony.com/schema/dic/services/services-1.0.xsd">     <config>
        <!-- ... -->         <firewall name="default">
            <!-- ... -->
        </firewall>         <!-- require ROLE_ADMIN for /admin* -->
        <rule path="^/admin" role="ROLE_ADMIN" />
    </config></srv:container>
真简单!要测试效果,你需要让用户登录并看到页面。为了让事情变的有趣,在 /admin 下创建一个新页面 。例如,如果你使用annotations,创建下例代码:
YAML:# app/config/security.ymlsecurity:    # ...
    firewalls:        # ...
        default:            # ...
    access_control:        # require ROLE_ADMIN for /admin*
        - { path: ^/admin, roles: ROLE_ADMIN }

接下来,在 security.yml 中添加一个 access_control 入口,以令用户必先登录方可访问URL:

PHP:// app/config/security.php$container->loadFromExtension('security', array(
    'providers' => array(
        'in_memory' => array(
            'memory' => array(
                'users' => array(
                    'ryan' => array(
                        'password' => 'ryanpass',
                        'roles' => 'ROLE_USER',
                    ),
                    'admin' => array(
                        'password' => 'kitten',
                        'roles' => 'ROLE_ADMIN',
                    ),
                ),
            ),
        ),
    ),
    // ...));
XML:<!-- app/config/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        http://Symfony.com/schema/dic/services/services-1.0.xsd">     <config>
        <provider name="in_memory">
            <memory>
                <user name="ryan" password="ryanpass" roles="ROLE_USER" />
                <user name="admin" password="kitten" roles="ROLE_ADMIN" />
            </memory>
        </provider>
        <!-- ... -->
    </config></srv:container>
YAML:# app/config/security.ymlsecurity:
    providers:
        in_memory:
            memory:
                users:
                    ryan:
                        password: ryanpass
                        roles: 'ROLE_USER'
                    admin:
                        password: kitten
                        roles: 'ROLE_ADMIN'    # ...

你将学到关于 ROLE_ADMIN 以及后面的 2) 拒绝访问, Roles和其他授权 小节中的“拒绝访问”等更多内容。

太好了,如果你去访问 /admin

PHP:// app/config/security.php$container->loadFromExtension('security', array(
    // ...     'encoders' => array(
        'Symfony\Component\Security\Core\User\User' => 'plaintext',
    ),
    // ...));
XML:<!-- app/config/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        http://Symfony.com/schema/dic/services/services-1.0.xsd">     <config>
        <!-- ... -->         <encoder class="Symfony\Component\Security\Core\User\User"            algorithm="plaintext" />
        <!-- ... -->
    </config></srv:container>
YAML:app/config/security.ymlsecurity:    # ...
    encoders:
        Symfony\Component\Security\Core\User\User: plaintext    # ...
Tellement simple ! Pour tester l'effet, vous devez demander aux utilisateurs de se connecter et de voir la page. Pour rendre les choses intéressantes, créez une nouvelle page sous /admin. Par exemple, si vous utilisez des annotations, créez le code suivant :

PHP:// app/config/security.php$container->loadFromExtension('security', array(
    // ...     'encoders' => array(
        'Symfony\Component\Security\Core\User\User' => array(
            'algorithm' => 'bcrypt',
            'cost' => 12,
        )
    ),
    // ...));

Ensuite, ajoutez une entrée access_control dans security.yml afin que les utilisateurs doivent se connecter premier à accéder à l'URL :
222.png

XML:<!-- app/config/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        http://Symfony.com/schema/dic/services/services-1.0.xsd">     <config>        <!-- ... -->         <encoder class="Symfony\Component\Security\Core\User\User"            algorithm="bcrypt"            cost="12" />         <!-- ... -->    </config></srv:container>
YAML:# app/config/security.ymlsecurity:    # ...
    encoders:
        Symfony\Component\Security\Core\User\User:
            algorithm: bcrypt
            cost: 12
1

Vous en apprendrez davantage sur ROLE_ADMIN et ce qui suit 2) Accès refusé, rôles et autres autorisations
"Accès refusé" et plus encore dans la section.

Super, si vous visitez /admin, vous verrez une fenêtre contextuelle de connexion pour l'authentification HTTP Basic :

Mais, sous quelle identité vous connectez-vous ? D’où viennent les utilisateurs (les informations) ?
Vous souhaitez utiliser une forme traditionnelle ? très bien! Voir

Comment créer un formulaire de connexion traditionnel. Quelles autres méthodes (d'authentification) sont prises en charge ? Reportez-vous à la Référence de configuration

ou à la
créez la vôtre
. 🎜🎜🎜🎜🎜🎜Si votre programme se connecte via un service tiers tel que Google, Facebook ou Twitter, veuillez vous référer au pack communautaire 🎜HWIOAuthBundle🎜. 🎜🎜🎜

B) Configurez "comment charger les utilisateurs"

Lorsque vous entrez le nom d'utilisateur, Symfony chargera les informations de l'utilisateur depuis quelque part. C'est ce qu'on appelle le « fournisseur d'utilisateurs » et il est de votre responsabilité de le configurer. Symfony dispose d'un moyen intégré pour charger les utilisateurs depuis la base de données, mais il est également possible de créer votre propre fournisseur d'utilisateurs.

Le moyen le plus simple (mais avec de nombreuses limitations) est de configurer Symfony pour charger directement les utilisateurs qui y sont programmés à partir du fichier security.yml. C'est ce qu'on appelle un fournisseur "en mémoire", mais il est préférable de le considérer comme un fournisseur "en configuration" security.yml 文件里直接加载写死在其中的用户。这被称为“in memory” provider,但把它观想为“in configuration” provider更合适些

$  php bin/console security:encode-password
PHP:// app/config/security.php$container->loadFromExtension('security', array(
    // ...     'providers' => array(
        'in_memory' => array(
            'memory' => array(
                'users' => array(
                    'ryan' => array(
                        'password' => 'a$LCY0MefVIEc3TYPHV9SNnuzOfyr2p/AXIGoQJEDs4am4JwhNz/jli',
                        'roles' => 'ROLE_USER',
                    ),
                    'admin' => array(
                        'password' => 'a$cyTWeE9kpq1PjqKFiWUZFuCRPwVyAZwm4XzMZ1qPUFl7/flCM3V0G',
                        'roles' => 'ROLE_ADMIN',
                    ),
                ),
            ),
        ),
    ),
    // ...));
XML:<!-- app/config/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        http://Symfony.com/schema/dic/services/services-1.0.xsd">     <config>
        <!-- ... -->         <provider name="in_memory">
            <memory>
                <user name="ryan" password="a$LCY0MefVIEc3TYPHV9SNnuzOfyr2p/AXIGoQJEDs4am4JwhNz/jli" roles="ROLE_USER" />
                <user name="admin" password="a$cyTWeE9kpq1PjqKFiWUZFuCRPwVyAZwm4XzMZ1qPUFl7/flCM3V0G" roles="ROLE_ADMIN" />
            </memory>
        </provider>
    </config></srv:container>

类似 firewalls,你可以拥有多个 providers ,但你几乎只需要一个。如果你确实 拥有多个,你可以在防火墙的 provider 键(如 provider:in_memory

YAML:# app/config/security.ymlsecurity:    # ...
    providers:
        in_memory:
            memory:
                users:
                    ryan:
                        password: a$LCY0MefVIEc3TYPHV9SNnuzOfyr2p/AXIGoQJEDs4am4JwhNz/jli
                        roles: 'ROLE_USER'
                    admin:
                        password: a$cyTWeE9kpq1PjqKFiWUZFuCRPwVyAZwm4XzMZ1qPUFl7/flCM3V0G
                        roles: 'ROLE_ADMIN'
PHP:// app/config/security.php$container->loadFromExtension('security', array(
    // ...     'firewalls' => array(
        // ...
        'default' => array(
            // ...
        ),
    ),
   'access_control' => array(
       // require ROLE_ADMIN for /admin*
        array('path' => '^/admin', 'role' => 'ROLE_ADMIN'),
    ),));
XML:<!-- app/config/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        http://Symfony.com/schema/dic/services/services-1.0.xsd">     <config>
        <!-- ... -->         <firewall name="default">
            <!-- ... -->
        </firewall>         <!-- require ROLE_ADMIN for /admin* -->
        <rule path="^/admin" role="ROLE_ADMIN" />
    </config></srv:container>
Semblable aux pare-feu, vous pouvez avoir plusieurs fournisseurs , mais vous n’en avez presque besoin que d’un. Si vous en avez

plusieurs, vous pouvez configurer "le
quel
utiliser" sous la clé provider du pare-feu (par exemple provider:in_memory).

Référence
Comment utiliser plusieurs fournisseurs d'utilisateurs
pour plus de détails sur la configuration de plusieurs fournisseurs. 🎜🎜🎜

Essayez de vous connecter avec le nom d'utilisateur admin et le mot de passe kitten. Vous devriez voir une erreur ! admin 和密码 kitten 来登录。你应该看到一个错误!

No encoder has been configured for account "SymfonyComponentSecurityCoreUserUser"

要修复此问题 ,添加一个 encoders 健:

YAML:# app/config/security.ymlsecurity:    # ...
    firewalls:        # ...
        default:            # ...
    access_control:        # require ROLE_ADMIN for /admin*
        - { path: ^/admin, roles: ROLE_ADMIN }
PHP:// app/config/security.php$container->loadFromExtension('security', array(
    // ...     'access_control' => array(
        array('path' => '^/admin/users', 'role' => 'ROLE_SUPER_ADMIN'),
        array('path' => '^/admin', 'role' => 'ROLE_ADMIN'),
    ),));
XML:<!-- app/config/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        http://Symfony.com/schema/dic/services/services-1.0.xsd">     <config>
        <!-- ... -->         <rule path="^/admin/users" role="ROLE_SUPER_ADMIN" />
        <rule path="^/admin" role="ROLE_ADMIN" />
    </config></srv:container>

User providers加载用户信息,并将其置于一个 User 对象中。如果你从数据库中加载用户 或者 从其他来源加载,你需要使用自定义的User类。但当你使用“in memory” provider时,它直接给了你一个 SymfonyComponentSecurityCoreUserUser 对象。

无论你使用什么样的User类,你都需要去告诉Symfony它们的密码加密算法是什么。在本例中,密码只是明文的文本,但很快,你要把它改成 bcrypt

如果你现在刷新,你就会登录进来!web除错工具栏会告诉你,你是何人,你的roles(角色)是什么:

4444t.png

由于此URL需要的是 ROLE_ADMIN ,如果你登录的是 ryan 用户,将被拒绝访问。更多内容参考后面的 [URL受到保护的条件(access_control](#catalog9)。

从数据库加载用户 

如果你想通过Doctrine Orm加载用户,很容易!参考 如何从数据库中(Entity Provider)加载Security系统之用户 以了解全部细节。

C) 对用户密码进行加密 

不管用户是存储在 security.yml 里,数据库里还是其他地方,你都需要去加密其密码。堪用的最好算法是 bcrypt

Aucun encodeur n'a été configuré pour le compte "SymfonyComponentSecurityCoreUserUser"


Pour résoudre ce problème, ajoutez une clé encoders : # 🎜🎜#
YAML:# app/config/security.ymlsecurity:    # ...
    access_control:
        - { path: ^/admin/users, roles: ROLE_SUPER_ADMIN }
        - { path: ^/admin, roles: ROLE_ADMIN }
// ... public function helloAction($name){
    // The second parameter is used to specify on what object the role is tested.
    // 第二个参数用于指定“要将role作用到什么对象之上”
    $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!');
    // }     // ...}
// ...use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; /**
 * @Security("has_role('ROLE_ADMIN')")
 */public function helloAction($name){
    // ...}

Les fournisseurs d'utilisateurs chargent les informations utilisateur et les placent dans un objet Utilisateur. Si vous chargez des utilisateurs à partir de la base de données ou chargez à partir d'autres sources , vous devez utiliser une classe User personnalisée. Mais lorsque vous utilisez le fournisseur "en mémoire", il vous donne directement un objet SymfonyComponentSecurityCoreUserUser.


Quelle que soit la classe d'utilisateurs que vous utilisez, vous devez indiquer à Symfony quel est son algorithme de cryptage de mot de passe. Dans ce cas, le mot de passe n'est qu'un texte en clair, mais vous souhaiterez bientôt le changer en bcrypt.

Si vous actualisez maintenant, vous serez connecté ! La barre d'outils de débogage Web vous dira qui vous êtes et quels sont vos rôles :

4444t.png
Puisque cette URL nécessite ROLE_ADMIN, si vous L'utilisateur connecté est ryan et l'accès lui sera refusé. Pour plus d'informations, veuillez vous référer aux [URL protégées conditions (access_control](#catalog9).

Charger les utilisateurs depuis la base de données

Si vous souhaitez charger des utilisateurs via Doctrine Orm, c'est simple ! Reportez-vous à Comment charger les utilisateurs de la base de données (Entity Provider)Charger l'utilisateur du système de sécurité pour connaître tous les détails # 🎜🎜# Bien entendu, le mot de passe de l'utilisateur doit maintenant être crypté par cet algorithme spécifié. Pour les utilisateurs codés en dur (dans config.yml), vous pouvez le faire avec la commande intégrée : ## 🎜🎜#
PHP:<?php if ($view['security']->isGranted(new Expression(
    '"ROLE_ADMIN" in roles or (user and user.isSuperAdmin())'))): ?>
    <a href="...">Delete</a><?php endif; ?>

C) Crypter le mot de passe de l'utilisateur ¶< /a>

PHP:<?php if ($view['security']->isGranted('ROLE_ADMIN')): ?>
    <a href="...">Delete</a><?php endif ?>
Twig:{% if is_granted('ROLE_ADMIN') %}
    <a href="...">Delete</a>{% endif %}
    if (!$this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) {
        throw $this->createAccessDeniedException();
    }     // ...}
#🎜🎜##🎜🎜##🎜🎜#
Twig:{% if is_granted(expression(
    '"ROLE_ADMIN" in roles or (user and user.isSuperAdmin())')) %}
    <a href="...">Delete</a>{% endif %}
#🎜🎜##🎜🎜##🎜🎜##🎜🎜##🎜🎜#

Cela vous apportera quelque chose comme ceci (le mot de passe est crypté) :

public function indexAction(){
    if (!$this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) {
        throw $this->createAccessDeniedException();
    }     $user = $this->getUser();     // the above is a shortcut for this / 上面的写法是通过以下取法(再进行授权)的快捷方式
    $user = $this->get('security.token_storage')->getToken()->getUser();}
use Symfony\Component\HttpFoundation\Response;
// ... public function indexAction(){
  // ...     return new Response('Well hi there '.$user->getFirstName());}
public function indexAction(UserInterface $user = null){
    // $user is null when not logged-in or anon.
    // 当用户没有登陆,或者是anno.时,$user是null}

Maintenant, tout est comme avant. Mais si vous avez des utilisateurs dynamiques (par exemple, dans une base de données) dont les mots de passe sont chiffrés avant d'être stockés dans la base de données, comment pouvez-vous les chiffrer par programme ? Ne vous inquiétez pas, reportez-vous à Crypter le mot de passe manuellement pour plus de détails.

La prise en charge de cet algorithme de cryptage dépend de votre version de PHP, mais il inclut l'algorithme renvoyé par la fonction hash_algos PHP, et certains autres (tels que bcrypt) sont pris en charge. Voir la clé d'option encodeurs dans la Référence de sécurité bcrypt)都受到支持。参考 Security参考 中的 encoders à titre d'exemple.

Il est également possible d'utiliser différents algorithmes pour différents utilisateurs. Reportez-vous à Comment choisir dynamiquement un algorithme de cryptage de mot de passe pour plus de détails.

D) Configuration terminée !

Félicitations ! Vous disposez désormais d'un "système d'authentification" fonctionnel basé sur l'authentification de base HTTP et chargeant les utilisateurs à partir du fichier security.yml. security.yml 文件中加载用户的“验证系统”了。

根据你的设置,尚有后续步骤:

2) 拒绝访问,Roles和其他授权方式 

现在,用户可以通过 http_basic 或者其他方式来登录你的程序。了不起呀!现在你需要学习如何拒绝访问(deny access)并且能与User对象一起工作。这被称为authorization(授权),它的工作是决定用户是否可以访问某些资源(如一个URL、一个model对象、一个被调用的方法等...)。

授权过程分为两个不同的方面:

  1. 用户在登录时收到一组特定的Roles(角色。如 ROLE_ADMIN)。

  2. 你添加代码,以便某个资源(例如url、控制器)需要一个特定“属性”(多数时候就是一个类似 ROLE_ADMIN 的role)才能被访问到。

除了roles(如 ROLE_ADMIN ),你还可以使用其他属性/字符串来(如 EDITEn fonction de vos paramètres, les étapes suivantes sont à suivre :

ou < a href="/doc/current/security/custom_authentication_provider.html">Certains
entièrement personnalisés
  • 🎜 pour charger des utilisateurs de différentes sources, comme Base de données 🎜 ou autre source 🎜 ; 🎜
  • 🎜 dans

    2) Refuser l'accès, les rôles et autres méthodes d'autorisation ¶🎜

    🎜Désormais, les utilisateurs peuvent se connecter à votre programme via http_basic ou d'autres méthodes. Incroyable! Vous devez maintenant apprendre à refuser l'accès et à utiliser des objets utilisateur. C'est ce qu'on appelle une autorisation (autorisation), et son rôle est de déterminer si l'utilisateur peut accéder à certaines ressources (comme une URL, un objet modèle, une méthode appelée, etc...). 🎜🎜Le processus d'autorisation est divisé en deux aspects différents : 🎜
    1. 🎜Les utilisateurs reçoivent un ensemble spécifique de rôles (rôles. Tels que ROLE_ADMIN) lors de la connexion. 🎜
    2. 🎜Vous ajoutez du code pour qu'une ressource (par exemple, une URL, un contrôleur) nécessite un "attribut" spécifique (principalement un rôle comme ROLE_ADMIN) avant de pouvoir y accéder. 🎜
    🎜En plus des rôles (tels que ROLE_ADMIN ), vous pouvez également utiliser d'autres attributs/chaînes (tels que EDIT) pour protéger une ressource et la rendre efficace en utilisant des électeurs ou le système ACL de Symfony. Ceci est extrêmement utile lorsque vous devez vérifier si l'utilisateur A peut "modifier" l'objet B (par exemple, un produit avec l'identifiant 5). Référence 🎜Listes de contrôle d'accès (ACL) : Protection des objets de base de données individuels🎜. 🎜🎜🎜

    Rôles/rôles

    Lorsqu'un utilisateur se connecte, il recevra un ensemble de rôles (tels que ROLE_ADMIN). Dans l'exemple ci-dessus, ces (rôles) sont codés en dur dans security.yml. Si vous chargez des utilisateurs depuis la base de données, ils doivent être stockés dans une colonne du tableau. ROLE_ADMIN)。在上例中,这些(roles)都被写死到 security.yml 中了。如果你从数据库中加载用户,它们应该存在了表的某一列中。

    你要分给一个用户的所有roles,一定要以 ROLE_ 前缀开始。否则,它们不会被Symfony的Security系统按常规方式来操作(除非使用高级手段,否则你把 FOO 这样的role分给一个用户,然后像 下面这样 去检查 FOO 是行不通的)。

    roles很简单,而且基本上都是你根据需要自行创造的字符串。例如,如果你打算限制访问你网站博客的admin部分,可以使用ROLE_BLOG_ADMIN 这个role来进行保护。role毋须在其他地方定义-你就可以开始用它了。

    确保每个用户至少有一个 角色,否则他们会被当作未验证之人。常见的做法就是给每个 普通用户一个 ROLE_USER

    你还可以指定role层级,此时,拥有某些roles意味着你同时拥有了其他的roles。

    添加代码以拒绝访问 

    要拒绝访问(deny access)某些东东,有两种方式可以实现:

    通过条件匹配来保护URL(access_control) 

    对程序的某一部分进行保护时的最基本方法是对URL进行完整的条件匹配。之前你已看到,任何匹配了正则表达式 ^/admin 的页面都需要 ROLE_ADMIN

    Tous les rôles que vous souhaitez attribuer à un utilisateur doivent commencer par le préfixe ROLE_ . Sinon, ils ne seront pas exploités par le système de sécurité de Symfony de la manière normale (sauf si vous utilisez des moyens avancés, sinon vous attribuez un rôle comme FOO à un utilisateur, puis comme Vérifier FOO comme ça
    ne fonctionnera pas).
    les rôles sont très simples et ce sont essentiellement des chaînes que vous créez en fonction de vos besoins. Par exemple, si vous envisagez de restreindre l'accès à la section d'administration du blog de votre site Web, vous pouvez utiliser le rôle ROLE_BLOG_ADMIN pour la protéger. Le rôle n'a pas besoin d'être défini ailleurs : vous pouvez simplement commencer à l'utiliser.
    Assurez-vous que chaque utilisateur a au moins un rôle, sinon il sera traité comme inconnu La personne qui valide. Une approche courante consiste à attribuer à chaque utilisateur ordinaire un ROLE_USER.
    🎜Vous pouvez également spécifier le niveau du rôle. À l'heure actuelle, posséder certains rôles signifie que vous possédez également d'autres rôles. 🎜🎜Ajoutez un code pour refuser l'accès
    ¶🎜🎜🎜Pour refuser l'accès à quelque chose, il existe deux typesCela peut être réalisé par : 🎜

    ; Correspondance conditionnelle réussie pour protéger l'URL (access_control) ¶🎜

    🎜La méthode la plus élémentaire pour protéger une certaine partie du programme est de protéger la correspondance de condition URL complète. Comme vous l'avez vu précédemment, toute page correspondant à l'expression régulière ^/admin nécessite ROLE_ADMIN : 🎜
    // yay! Use this to see if the user is logged in// 耶!使用这个来查看用户是否已登陆if (!$this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) {
        throw $this->createAccessDeniedException();} // boo :(. Never check for the User object to see if they're logged in// 哄!:(. 切勿通过检查User对象来判断用户是否已登陆if ($this->getUser()) { }
    PHP:<?php if ($view['security']->isGranted('IS_AUTHENTICATED_FULLY')): ?>
        <p>Username: <?php echo $app->getUser()->getUsername() ?></p><?php endif; ?>
    🎜🎜🎜🎜🎜
    Twig:{% if is_granted('IS_AUTHENTICATED_FULLY') %}
        <p>Username: {{ app.user.username }}</p>{% endif %}
    🎜🎜🎜🎜🎜

    C'est bien de pouvoir protéger toute la zone (à laquelle appartient l'URL), mais vous souhaiterez peut-être aussi protéger une action spécifique du contrôleur.

    Vous pouvez définir autant de conditions de correspondance d'URL que vous le souhaitez - chaque condition est une expression régulière. Mais , un seul un sera jumelé. Symfony commencera à regarder en haut (dans le fichier) et terminera dès qu'il trouvera une entrée dans access_control qui correspond à l'URL. access_control 中的某个入口与URL相匹配,就立即结束。

    PHP:// app/config/security.php$container->loadFromExtension('security', array(
        // ...     'firewalls' => array(
            'secured_area' => array(
                // ...
                'logout' => array('path' => '/logout', 'target' => '/'),
            ),
        ),));
    Twig:<!-- app/config/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        http://Symfony.com/schema/dic/services/services-1.0.xsd">     <config>
            <!-- ... -->         <firewall name="secured_area">
                <!-- ... -->
                <logout path="/logout" target="/" />
            </firewall>
        </config></srv:container>
    YAML:# app/config/security.ymlsecurity:    # ...
        firewalls:
            secured_area:            # ...
                logout:
                    path:   /logout
                    target: /

    在path中加了一个 ^ 是指,仅当URL“按照正则条件那样起头”时,才会匹配到。例如,一个path若只有 /admin(不包含 ^)则会匹配到 /admin/foo 但同时也匹配了 /foo/admin 这种。

    理解access_control是如何工作的

    access_control 部分异常强大,但如果你不明白它的工作原理,它也会很危险(毕竟涉及到安全性)。 access_control 除了匹配URL,还可匹配IP地址、主机名和HTTP method。它也可以用于将用户重定向到 https 版本的URL条件中去。

    要了解这一切,参考 Security的access_control是如何工作的

    保护控制器和代码中的其他部分 

    在控制器中你可以轻松谢绝访问:

    PHP:// app/config/routing.phpuse Symfony\Component\Routing\RouteCollection;use Symfony\Component\Routing\Route; $collection = new RouteCollection();$collection->add('logout', new Route('/logout')); return $collection;

    两种情况下,一个特殊的 AccessDeniedException 会被抛出,这最终触发了Symfony内部的一个403 HTTP响应。

    就是这样!如果是尚未登录的用户,他们会被要求登录(如,重定向到登录页面)。如果他们已经 登录,但不具备 ROLE_ADMIN 角色,则会被显示403拒绝访问页面(此页可以 自定义)。如果他们已登录同时拥有正确的roles,代码就会继续执行。

    多亏了SensioFrameworkExtraBundle,你可以在控制器中使用annotations

    XML:<!-- app/config/routing.xml --><?xml version="1.0" encoding="UTF-8" ?><routes xmlns="http://Symfony.com/schema/routing"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:schemaLocation="http://Symfony.com/schema/routing        http://Symfony.com/schema/routing/routing-1.0.xsd">     <route id="logout" path="/logout" /></routes>

    参考 FrameworkExtraBundle 以了解更多。

    模版中的访问控制 

    如果你想在模版中检查当前用户是否具有一个role,可以使用内置的 is_granted()

    YAML:# app/config/routing.ymllogout:
        path: /logout
    PHP:// app/config/security.php$container->loadFromExtension('security', array(
        // ...     'role_hierarchy' => array(
            'ROLE_ADMIN'       => 'ROLE_USER',
            'ROLE_SUPER_ADMIN' => array(
                'ROLE_ADMIN',
                'ROLE_ALLOWED_TO_SWITCH',
            ),
        ),));

    XML:<!-- app/config/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        http://Symfony.com/schema/dic/services/services-1.0.xsd">     <config>
            <!-- ... -->         <role id="ROLE_ADMIN">ROLE_USER</role>
            <role id="ROLE_SUPER_ADMIN">ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH</role>
        </config></srv:container>
    L'ajout d'un ^ au chemin signifie qu'il ne sera mis en correspondance que si l'URL "démarre selon les conditions habituelles". Par exemple, si un chemin ne contient que /admin (sans ^), il correspondra à /admin/foo mais aussi à . foo/admin Ce genre de. 🎜

    Comprendre comment fonctionne access_control

    🎜 Le access_control La partie est incroyablement puissante, mais elle peut aussi être dangereuse si vous ne comprenez pas comment elle fonctionne (la sécurité est impliquée, après tout). access_control En plus de faire correspondre les URL, il peut également faire correspondre les adresses IP, les noms d'hôte et les méthodes HTTP. Il peut également être utilisé pour rediriger les utilisateurs vers la version https de la condition d'URL. 🎜🎜Pour comprendre tout cela, reportez-vous à Comment fonctionne le contrôle d'accès de Security🎜. 🎜🎜🎜

    Protégez les contrôleurs et d'autres parties de votre code ¶🎜

    🎜Dans les contrôleurs, vous pouvez facilement refuser l'accès : 🎜
    YAML:# app/config/security.ymlsecurity:    # ...
        role_hierarchy:
            ROLE_ADMIN:       ROLE_USER
            ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
    🎜Dans les deux cas, un
    AccessDeniedException🎜 sera levée, ce qui déclenchera finalement une réponse HTTP 403 au sein de Symfony.
    🎜🎜Ça y est ! Si l'utilisateur n'est pas encore connecté, il lui sera demandé de se connecter (par exemple, redirigé vers la page de connexion). S'ils sont déjà connectés mais n'ont pas le rôle ROLE_ADMIN, une page 403 Accès refusé leur sera présentée (cette page peut
    custom 🎜). S'ils sont connectés et disposent des rôles corrects, le code continuera à s'exécuter. 🎜🎜Grâce à SensioFrameworkExtraBundle, vous pouvez utiliser des annotations dans les contrôleurs🎜rrreee🎜Référez-vous à FrameworkExtraBundle🎜 pour en savoir plus.
    🎜

    Contrôle d'accès dans les modèles ¶🎜

    🎜Si vous souhaitez vérifier dans le modèle si l'utilisateur actuel a un rôle, vous pouvez utiliser la fonction d'assistance intégrée is_granted() : 🎜rrreee🎜rrreee🎜

    Protégez d'autres services

    Si vous écrivez un code similaire comme "Protect Controller", n'importe où dans Symfony peut être protégé. Disons que vous disposez d'un service (c'est-à-dire une classe php) pour envoyer des e-mails. Vous pouvez restreindre l'utilisation de cette classe - quel que soit l'endroit où elle est utilisée - à des utilisateurs spécifiques uniquement.

    Référez-vous à Comment protéger les services et les méthodes dans un programme pour en savoir plus.

    Vérifiez si l'utilisateur est connecté (IS_AUTHENTICATED_FULLY)

    Jusqu'à présent, vous avez vérifié l'accès basé sur les rôles - ces chaînes commençant par le préfixe ROLE_ qui sont attribuées aux utilisateurs. Cependant, si vous ROLE_ 前缀开头的字符串,被分配给了用户。但是,如果你 想检查用户是否登录(并不关心什么role不role的),那么你可以使用 IS_AUTHENTICATED_FULLY// ... public function helloAction($name){

    rrreee

    你当然也可以使用在 access_control 中使用它。

    IS_AUTHENTICATED_FULLY 不是一个role,但是它的某些行为又像是role,并且每个成功登录的用户都有这么一个。事实上,类似的特殊属性共有三个: