Security
Edit this pageWarning: You are browsing the documentation for Symfony 2.3, which is no longer maintained.
Read the updated version of this page for Symfony 6.3 (the current stable version).
Security
Authentication and Firewalls (i.e. Getting the User's Credentials)
You can configure Symfony to authenticate your users using any method you want and to load user information from any source. This is a complex topic, but the Security Cookbook Section has a lot of information about this.
Regardless of your needs, authentication is configured in security.yml
,
primarily under the firewalls
key.
Best Practice
Unless you have two legitimately different authentication systems and
users (e.g. form login for the main site and a token system for your
API only), we recommend having only one firewall entry with the anonymous
key enabled.
Most applications only have one authentication system and one set of users. For this reason, you only need one firewall entry. There are exceptions of course, especially if you have separated web and API sections on your site. But the point is to keep things simple.
Additionally, you should use the anonymous
key under your firewall. If
you need to require users to be logged in for different sections of your
site (or maybe nearly all sections), use the access_control
area.
Best Practice
Use the bcrypt
encoder for encoding your users' passwords.
If your users have a password, then we recommend encoding it using the bcrypt
encoder, instead of the traditional SHA-512 hashing encoder. The main advantages
of bcrypt
are the inclusion of a salt value to protect against rainbow
table attacks, and its adaptive nature, which allows to make it slower to
remain resistant to brute-force search attacks.
With this in mind, here is the authentication setup from our application, which uses a login form to load users from the database:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
# app/config/security.yml
security:
encoders:
AppBundle\Entity\User: bcrypt
providers:
database_users:
entity: { class: AppBundle:User, property: username }
firewalls:
secured_area:
pattern: ^/
anonymous: true
form_login:
check_path: login
login_path: login
logout:
path: security_logout
target: homepage
# ... access_control exists, but is not shown here
Tip
The source code for our project contains comments that explain each part.
Authorization (i.e. Denying Access)
Symfony gives you several ways to enforce authorization, including the access_control
configuration in security.yml and
using isGranted on the security.context
service directly.
Best Practice
- For protecting broad URL patterns, use
access_control
; - Check security directly on the
security.context
service whenever you have a more complex situation.
There are also different ways to centralize your authorization logic, like with a custom security voter or with ACL.
Best Practice
- For fine-grained restrictions, define a custom security voter;
- For restricting access to any object by any user via an admin interface, use the Symfony ACL.
Manually Checking Permissions
If you cannot control the access based on URL patterns, you can always do the security checks in PHP:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
// ...
/**
* @Route("/{id}/edit", name="admin_post_edit")
*/
public function editAction($id)
{
$post = $this->getDoctrine()->getRepository('AppBundle:Post')
->find($id);
if (!$post) {
throw $this->createNotFoundException();
}
if (!$post->isAuthor($this->getUser())) {
throw new AccessDeniedException();
}
// ...
}
Security Voters
If your security logic is complex and can't be centralized into a method
like isAuthor()
, you should leverage custom voters. These are an order
of magnitude easier than ACLs and will give
you the flexibility you need in almost all cases.
First, create a voter class. The following example shows a voter that implements
the same getAuthorEmail
logic you used above:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
namespace AppBundle\Security;
use Symfony\Component\Security\Core\Authorization\Voter\AbstractVoter;
use Symfony\Component\Security\Core\User\UserInterface;
// AbstractVoter class requires Symfony 2.6 or higher version
class PostVoter extends AbstractVoter
{
const CREATE = 'create';
const EDIT = 'edit';
protected function getSupportedAttributes()
{
return array(self::CREATE, self::EDIT);
}
protected function getSupportedClasses()
{
return array('AppBundle\Entity\Post');
}
protected function isGranted($attribute, $post, $user = null)
{
if (!$user instanceof UserInterface) {
return false;
}
if ($attribute === self::CREATE && in_array('ROLE_ADMIN', $user->getRoles(), true)) {
return true;
}
if ($attribute === self::EDIT && $user->getEmail() === $post->getAuthorEmail()) {
return true;
}
return false;
}
}
To enable the security voter in the application, define a new service:
1 2 3 4 5 6 7 8
# app/config/services.yml
services:
# ...
post_voter:
class: AppBundle\Security\PostVoter
public: false
tags:
- { name: security.voter }
Now, you can use the voter with the security.context
service:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
// ...
/**
* @Route("/{id}/edit", name="admin_post_edit")
*/
public function editAction($id)
{
$post = // query for the post ...
if (!$this->get('security.context')->isGranted('edit', $post)) {
throw new AccessDeniedException();
}
}
Learn More
The FOSUserBundle, developed by the Symfony community, adds support for a database-backed user system in Symfony. It also handles common tasks like user registration and forgotten password functionality.
Enable the Remember Me feature to allow your users to stay logged in for a long period of time.
When providing customer support, sometimes it's necessary to access the application as some other user so that you can reproduce the problem. Symfony provides the ability to impersonate users.
If your company uses a user login method not supported by Symfony, you can develop your own user provider and your own authentication provider.