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:
Initialization
security.yml
settings (authentication/verification );Denied access to your program (authorization/authorization );
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 inapp/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.
How to restrict firewalling to specific requests for more information and examples.
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:
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: ~
/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:
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:
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