Security


Symfony's security system is very powerful, but it can also be confusing when setting it up. In this large chapter, you will learn how to set up the security of your application step by step, from configuring the firewall and loading users, to denying access and retrieving user objects. Depending on your needs, sometimes doing the initial setup can be painful. Once complete, however, Symfony's security system is both flexible and (hopefully) fun to use.

Since there is a lot to say, this chapter is organized into several tomes:

  1. Initializationsecurity.yml settings (authentication/verification );

  2. Denied access to your program (authorization/authorization );

  3. Get the current User object;

They are broken down into many small (but still fascinating) chunks, like logging out and encryption user password.

1) Initialize security.yml settings (Authentication/verification)

##The security system is performed in

app/config/security.yml configuration. The default configuration is like this:

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 The key is the core of the security configuration. dev The firewall is not important, it just ensures that the Symfony development tools - that is, those URLs under /_profiler and /_wdt will not be blocked by your blocked by security.

You can also match a request against other details in the request (such as host). Read

How to restrict firewalling to specific requests for more information and examples.

All other URLs will be handled by the

default firewall (no pattern key means it can match all URL). You can think of the firewall as your security system, so it usually makes sense to have just one main firewall. But this doesn't not mean that every URL needs to be authenticated - the anonymous key will take care of this. In fact, if you go to the home page now, you will have access and will see that you are "verified" as anon.. Don’t be fooled by the “Yes” next to Authenticated, you are still just an anonymous user:

11.png

#You will learn later how to deny access to a specific URL or controller (action in) .

Security is

highly configurable, and all configuration options are shown in Security Configuration Reference, with some additional instructions.

A) Configure "how to enable users to be authenticated"

The main job of the firewall is to configure how to enable your users to be authenticated. Do they require a login form? Or HTTP basic authentication? Or an API token? Or all of the above?

Let's start with HTTP basic authentication (the old pop-up box). To activate this feature, add http_basic to the firewall:

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: ~
It’s so easy! To test the effect, you need to have users log in and see the page. To make things interesting, create a new page under /admin. For example, if you use annotations, create the following code:
// 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>');
    }}

Next, add an access_control entry in security.yml to allow users You must log in first to access the URL:

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>
YAML:# app/config/security.ymlsecurity:    # ...
    firewalls:        # ...
        default:            # ...
    access_control:        # require ROLE_ADMIN for /admin*
        - { path: ^/admin, roles: ROLE_ADMIN }

You will learn about ROLE_ADMIN and the following 2 ) Access Denied, "Access Denied" and more in the Roles and Other Authorizations section.

Great, if you visit /admin, you will see a pop-up login for HTTP Basic authentication:

222.png

But, as what identity do you log in? Where do users (information) come from?

Want to use a traditional form? very good! Refer to How to build a traditional login form. What other (authentication) methods are supported? Refer to the Configuration Reference or to build your own .

If your program completes login through a third-party service such as Google, Facebook or Twitter, please refer to the HWIOAuthBundle community bundle.

B) Configure "how to load users"

When you enter the user name, Symfony will load the user's information from somewhere. This is the so-called "user provider" and it is your responsibility to configure it. Symfony has a built-in way to load users from the database, but it is also possible to create your own user provider.

The simplest way (but with many limitations) is to configure Symfony to directly load the users programmed in it from the security.yml file. This is called an "in memory" provider, but it's better to think of it as an "in configuration" provider

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'    # ...

Similar to firewalls, you can have multiple providers , but you almost only need one. If you indeed have multiple, you can configure "Which one to use under the provider key of the firewall (e.g. provider: in_memory) ”provider.

Reference How to use multiple User Providers to learn the full details of multiple providers setup.

Try logging in with username admin and password kitten. You should see an error!

No encoder has been configured for account "Symfony\Component\Security\Core\User\User"

To fix this, add a encoders Key:

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    # ...

User providers load user information and place it in a User object. If you load users from a database or load from other sources, you need to use a custom User class. But when you use the "in memory" provider, it gives you a Symfony\Component\Security\Core\User\User object directly.

No matter what User class you use, you need to tell Symfony what their password encryption algorithm is. In this case, the password is just clear text, but soon, you'll want to change it to bcrypt.

If you refresh now, you will be logged in! The web debugging toolbar will tell you who you are and what your roles are:

4444t.png

Because this URL requires ROLE_ADMIN , if you are logged in as user ryan, access will be denied. For more information, refer to the following [URL protected conditions (access_control](#catalog9).

Load users from the database

If you want to load through Doctrine Orm User, it's easy! Refer to How to load Security system users from the database (Entity Provider) for full details.

C) Encrypt user password

Whether the user is stored in security.yml, in the database, or elsewhere, you need to encrypt his password. The best algorithm available is bcrypt:

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


## Of course, the user password is now required Encrypted by this specified algorithm. For users who are hardcoded (in config.yml), you can do it with the built-in command:

##
1
$  php bin/console security:encode-password

It will bring you something like this (the password is encrypted):

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>
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'

Now everything is the same as before. But if you have dynamic users (eg, in a database) whose passwords are encrypted before being stored in the database, how can you programmatically encrypt them? Don't worry, refer to Manually Encrypt Passwords for details.

Whether this encryption algorithm is supported depends on your PHP version, but it includes the algorithm returned by the hash_algos PHP function, and some others (such as bcrypt) are supported. See the encoders option key in Security Reference as an example.

It is also possible to use different algorithms for different users. Refer to How to Dynamically Choose a Password Encryption Algorithm for more details.

D) Configuration completed!

congratulations! Now you have a working "authentication system" based on HTTP basic authentication and loading users from the security.yml file.

Depending on your settings, there are subsequent steps:

2) Deny access, Roles and other authorization methods

Now, users can log in to your program through http_basic or other methods. Amazing! Now you need to learn how to deny access and work with User objects. This is called authorization (authorization), and its job is to determine whether the user can access certain resources (such as a URL, a model object, a called method, etc...).

The authorization process is divided into two different aspects:

  1. The user receives a specific set of Roles when logging in. Such as ROLE_ADMIN ).

  2. You add code so that a resource (e.g. url, controller) requires a specific "attribute" (mostly a role like ROLE_ADMIN) to be able to was visited.

In addition to roles (such as ROLE_ADMIN), you can also use other attributes/strings (such as EDIT ) to protect a resource and make them effective by using voters or Symfony's ACL system. This is useful when you need to check if user A can "edit" object B (for example, product with id 5). Reference Access Control Lists (ACLs): Protecting Individual Database Objects.

Roles/Role

When a user logs in, they will receive a set of roles (such as ROLE_ADMIN). In the above example, these (roles) are hard-coded into security.yml. If you load users from the database, they should be stored in a column of the table.

All the roles you want to assign to a user must start with the ROLE_ prefix. Otherwise, they will not be operated by Symfony's Security system in the normal way (unless using advanced means, otherwise you assign a role like FOO to a user, and then go like below Checking FOO will not work).

roles are very simple, and they are basically strings that you create according to your needs. For example, if you plan to restrict access to the admin section of your website's blog, you can use the ROLE_BLOG_ADMIN role to protect it. The role does not need to be defined elsewhere - you can just start using it.

Make sure each user has at least one role, otherwise they will be treated as unverified. A common approach is to give each ordinary user a ROLE_USER.

You can also specify the role level. At this time, owning certain roles means that you also own other roles.

Add code to deny access

To deny access to something, there are two ways to do it:

Pass conditions Matching to protect URL (access_control)

The most basic way to protect a certain part of the program is to perform complete conditional matching on the URL. You saw earlier that any page matching the regular expression ^/admin requires 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>
YAML:# app/config/security.ymlsecurity:    # ...
    firewalls:        # ...
        default:            # ...
    access_control:        # require ROLE_ADMIN for /admin*
        - { path: ^/admin, roles: ROLE_ADMIN }

It's nice to be able to protect the entire area (to which the URL belongs), but you may also want to protect a specific action of the controller.

If necessary, you can define as many URL matching conditions as you like - each condition is a regular expression. But , only and one will be matched. Symfony will start looking at the top (in the file) and end as soon as it finds an entry in access_control that matches the URL.

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>
YAML:# app/config/security.ymlsecurity:    # ...
    access_control:
        - { path: ^/admin/users, roles: ROLE_SUPER_ADMIN }
        - { path: ^/admin, roles: ROLE_ADMIN }

Adding a ^ to the path means that it will be matched only if the URL "starts according to the regular conditions". For example, if a path only contains /admin (excluding ^), it will match /admin/foo but also /foo/. admin This kind.

Understand how access_control works

access_control Parts are incredibly powerful, but if you don’t understand how it worksPrinciple, it can also be dangerous (it involves security after all). access_control In addition to matching URL, it can also match IP address, host name and HTTP method. It can also be used to redirect users to the https version of the URL condition.

To understand all this, refer to How Security's access_control works.

Protect the controller and other parts of the code

In the controller you can easily deny access:

// ... 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!');
    // }     // ...}

In both cases, a special AccessDeniedException will be thrown, which ultimately triggers a 403 HTTP response inside Symfony.

That's it! If the user is not logged in yet, they will be asked to log in (e.g., redirected to the login page). If they are logged in but do not have the ROLE_ADMIN role, they will be shown a 403 Access Denied page (this page can be customized). If they are logged in and have the correct roles, the code will continue executing.

Thanks to SensioFrameworkExtraBundle, you can use annotations in controllers

// ...use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; /**
 * @Security("has_role('ROLE_ADMIN')")
 */public function helloAction($name){
    // ...}

Refer to FrameworkExtraBundle to learn more.

Access control in templates

If you want to check whether the current user has a role in the template, you can use the built-in is_granted( ) helper function:

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 %}

Protect other services

If you write some similar code like "protecting the controller", anywhere in Symfony can be protected. Let's say you have a service (i.e. a php class) for sending emails. You can restrict the use of this class - regardless of where it is used - to only specific users.

Refer to How to protect services and methods in a program to learn more.

Check if the user is logged in (IS_AUTHENTICATED_FULLY)

So far, you have checked for role-based access - those starting with the ROLE_ prefix The string is assigned to the user. However, if you only want to check whether the user is logged in (and don't care about the role or not), then you can use IS_AUTHENTICATED_FULLY: // ... public function helloAction ($name){

    if (!$this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) {
        throw $this->createAccessDeniedException();
    }     // ...}

You can of course also use it in access_control.

IS_AUTHENTICATED_FULLY is not a role, but some of its behaviors are like roles, and every user who successfully logs in has such a role. In fact, there are three similar special attributes:

  • ##IS_AUTHENTICATED_REMEMBERED: All logged in users have it, even if they are logged in via " Remember me cookie" to log in. Even if you don't use the remember me function, you can still check whether the user is logged in through this attribute.

  • ##IS_AUTHENTICATED_FULLY

    : Similar to IS_AUTHENTICATED_REMEMBERED, but more robust. Users who log in based only on IS_AUTHENTICATED_REMEMBERED in the "remember me cookie" will not have IS_AUTHENTICATED_FULLY.

  • IS_AUTHENTICATED_ANONYMOUSLY

    : All users (even anonymous users) have this attribute - when the URL is placed in the whitelist It is useful to ensure that it can be accessed. Refer to How Security's access_control works to learn more.

  • You can also use expressions in templates:
PHP:<?php if ($view['security']->isGranted(new Expression(
    '"ROLE_ADMIN" in roles or (user and user.isSuperAdmin())'))): ?>
    <a href="...">Delete</a><?php endif; ?>

Twig:{% if is_granted(expression(
    '"ROLE_ADMIN" in roles or (user and user.isSuperAdmin())')) %}
    <a href="...">Delete</a>{% endif %}

For more details on expressions and security, refer to Security: Complex Access Controls Expressions.

Access Control Lists (ACLs): Protecting Individual Database Objects

Imagine that you are designing a blog where users can leave comments under a topic. You also want users to be able to edit their own comments, but other users shouldn't be able to. Additionally, as an admin user, you will want to be able to edit all comments.

To do this, you have two options:

  • Voters Allow users to write their own business logic (e.g., users can edit This article was created as they are) to check access. You might use this option - it's flexible enough to solve the above problems.

  • ACLs Allow you to create a database structure in which you can assign any objects to any user Any access rights (e.g., EDIT, VIEW). To use ACLs, you need an administrator user to grant custom access to your system through some administrative interface.

In both cases, you still need to implement deny access using a method similar to the previous example.

Get the user object

After verification, you can access the current user’s

User through the security.token_storage service object. In the controller, write this:

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();}


The user will be an object, and the class to which the object belongs depends on your

user provider.


##3.2

Obtaining user functions through method signatures was introduced from Symfony 3.2. If you inherit Controller, you can still get it by calling $this->getUser().

Now, any method can be called based on your User object. For example, if there is a getFirstName() method in the User object, you can use it:

use Symfony\Component\HttpFoundation\Response;
// ... public function indexAction(){
  // ...     return new Response('Well hi there '.$user->getFirstName());}

Always detect if the user is logged in

The initial verification of the user is very important. If not logged in, $user is one of null or anon. strings. Wait, why? Yes, it's weird. If you are not logged in, technically the user should be anon., although the getUser() shortcut method in the controller will turn this into null# for convenience ##. When using type hints for UserInterface and being logged in is optional, you can configure null values ​​for parameters:

public function indexAction(UserInterface $user = null){
    // $user is null when not logged-in or anon.
    // 当用户没有登陆,或者是anno.时,$user是null}

The view is this : You should always check whether the user is logged in before using the User object. This can be done using the

isGranted method (or access_control):

// 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()) { }

in the template To obtain the user


object, you can use the

app.user key in the twig template:

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 %}

Logging out/Log out


##Note that when using a firewall with http-basic authentication, there is no way to exit:
log out

is the only way Just tell the browser to stop sending your username and password with every request. Clearing the browser cache or restarting it often helps. Certain web development tools may also be useful.

Typically, you want the user to be able to log out. Fortunately, the firewall can help you handle this automatically when you activate the
logout

configuration parameter:

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: /
Next, you need to create a route for this URL (but no controller is required ):

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;
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>

YAML:# app/config/routing.ymllogout:
    path: /logout

That's it! Symfony will deauthenticate the current user by sending the user to /logout (or whatever path option you configure).

Once the user is logged out, they will be redirected to the path corresponding to the defined target parameter (such as homepage).

If you need to do something more interesting after logging out, you can specify a "logout success handler" by adding the success_handler key ), fill it in as the id of a service definition. The class of the service must implement the LogoutSuccessHandlerInterface interface. Reference Security Configuration Reference.

Roles by level

Instead of associating a large number of roles to users, by creating a role hierarchy, you can Define a set of "role inheritance rules":

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>
YAML:# app/config/security.ymlsecurity:    # ...
    role_hierarchy:
        ROLE_ADMIN:       ROLE_USER
        ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]

In the above configuration, user ROLE_ADMIN will also have the ROLE_USER role. ROLE_SUPER_ADMIN role, which also has ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH and ROLE_USER (inherited from ROLE_ADMIN).

Summary

Oh~well done! You've learned more than the basics of security. The hardest part is when you have custom requirements: like defining an authentication strategy (e.g., api tokens), complex authorization logic, and many other things (because security is inherently complex!).

Fortunately: there are many articles here that aim to clarify various situations. Also, refer to Security Reference. Many configuration options are not detailed, but it still helps to see the complete configuration tree.

good luck!