If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.
With a Subscription, click any sentence in the script to jump to that part of the video!
Login SubscribeThere are two main places where you can deny access. The first we just learned about: access_control
in security.yaml
:
security: | |
... lines 2 - 40 | |
access_control: | |
- { path: ^/admin, roles: ROLE_ADMIN } | |
... lines 43 - 44 |
It's simple - just a regular expression and a role. It's the best way to protect entire areas of your site - like everything under /admin
with ROLE_ADMIN
.
I do use access controls for things like that. But, most of the time, I prefer to control access at a more granular level. Open CommentAdminController
. Most of the time, I deny access right inside the controller.
To test this out - let's comment-out our access control:
security: | |
... lines 2 - 40 | |
access_control: | |
# - { path: ^/admin, roles: ROLE_ADMIN } | |
... lines 43 - 44 |
Back in CommentAdminController
, how can we deny access here? Simple: $this->denyAccessUnlessGranted()
and pass this a role: ROLE_ADMIN
:
... lines 1 - 10 | |
class CommentAdminController extends Controller | |
{ | |
... lines 13 - 15 | |
public function index(CommentRepository $repository, Request $request, PaginatorInterface $paginator) | |
{ | |
$this->denyAccessUnlessGranted('ROLE_ADMIN'); | |
... lines 19 - 32 | |
} | |
} |
That's it. Move over and refresh!
Nice! Try changing it to ROLE_USER
:
... lines 1 - 10 | |
class CommentAdminController extends Controller | |
{ | |
... lines 13 - 15 | |
public function index(CommentRepository $repository, Request $request, PaginatorInterface $paginator) | |
{ | |
$this->denyAccessUnlessGranted('ROLE_USER'); | |
... lines 19 - 32 | |
} | |
} |
Access granted! I love it!
But wait, there's more! As simple as this is, I like to use annotations. Check this out: delete the denyAccessUnlessGranted()
code. Instead, above the method, add @IsGranted()
to use an annotation that comes from SensioFrameworkExtraBundle: a bundle that we installed a long time ago via composer require annotations
. In double quotes, pass ROLE_ADMIN
:
... lines 1 - 6 | |
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted; | |
... lines 8 - 11 | |
class CommentAdminController extends Controller | |
{ | |
/** | |
... line 15 | |
* @IsGranted("ROLE_ADMIN") | |
*/ | |
public function index(CommentRepository $repository, Request $request, PaginatorInterface $paginator) | |
{ | |
... lines 20 - 32 | |
} | |
} |
Nice! Try it: refresh!
Access Denied by controller annotation
Pretty sweet. I know not everyone will love using annotations for this. So, if you don't love it, use the PHP version. No problem.
Oh, but the annotation does have one superpower. In addition to putting @IsGranted
above a controller method, you can also put it above the controller class. Above CommmentAdminController
, add @IsGranted("ROLE_ADMIN")
:
... lines 1 - 6 | |
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted; | |
... lines 8 - 11 | |
/** | |
* @IsGranted("ROLE_ADMIN") | |
*/ | |
class CommentAdminController extends Controller | |
{ | |
... lines 17 - 35 | |
} |
Now, every method inside of this controller... which is only one right now, will require this role. When you refresh... yep! Same error. That is an awesome way to deny access.
We know how to make sure a user has a role. But, how can we simply make sure a user is logged in, regardless of roles? Let's find out next - and - create our first admin users.
Hey Farry7,
Haha, good question! :D That you can also easily check it yourself... didn't you download the course code and follow the tutorials coding along with us? ;) ROLE_ADMIN is literally ROLE_ADMIN string in the DB on the user record, but because user may have a few roles - roles are stored as array that is serialized to string to store in the DB :) ROLE_ADMIN is just an arbitrary name, you can come up with any string, e.g. ROLE_ADMINISTRATOR.
Cheers!
Annotation @IsGranted can I somehow use it on multiple roles?
I have tried @IsGranted(["ROLE_ADMIN","ROLE_MANAGER"]) but this doesnt work.
I would like to check if the user has at least 1 of the roles.
Hey Peter K.!
Good question! You can use multiple roles *anywhere* in Symfony - the IsGranted() annotation, denyAccessUnlessGranted, and even in access_control I believe. But, I never do this, because, for me, it's not clear what passing 2 roles means. Is it an "OR" (ROLE_ADMIN or ROLE_MANAGER) or an "AND". The answer is "OR", but because it's not clear to look at, I don't prefer using it (https://github.com/symfony/.... Instead, I rely on role_hierarchy - i would probably give ROLE_ADMIN the ROLE_MANAGER role in the hierarchy. But, it depends on your needs - there is certainly nothing wrong with passing multiple roles :).
> btw ryan you have to update email just saw it in IsGranted.php :)
What do you mean? What email? :)
Cheers!
Oh, and I just realized I misread your first comment! IsGranted with multiple roles is NOT working? It should - it should have the same affect as passing denyAccessUnlessGranted() those same 2 roles. What are you seeing?
Cheers!
when using this:
/**
* @IsGranted(["ROLE_ADMIN","ROLE_MANAGER"])
*/
error:
Exception thrown when handling an exception (Symfony\Component\Config\Exception\FileLoaderLoadException: [Syntax Error] Expected PlainValue, got '[' at position 11 in class App\Controller\ResourcePlanningController in /Users/peterkosak/Desktop/symfony/test/config/routes/../../src/Controller/ (which is being imported from "/Users/peterkosak/Desktop/symfony/test/config/routes/annotations.yaml"). Make sure annotations are installed and enabled.)
when using without square [
/**
* @IsGranted("ROLE_ADMIN","ROLE_MANAGER")
*/
getting this
Exception thrown when handling an exception (Symfony\Component\Config\Exception\FileLoaderLoadException: [Syntax Error] Expected Value, got 'ROLE_MANAGER' at position 24 in class App\Controller\ResourcePlanningController in /Users/peterkosak/Desktop/symfony/test/config/routes/../../src/Controller/ (which is being imported from "/Users/peterkosak/Desktop/symfony/test/config/routes/annotations.yaml"). Make sure annotations are installed and enabled.)
it is screaming about annotation not installed but when I use only 1 role in annotation I will get Access Denied
Try this syntax:
/**
* @IsGranted({"ROLE_ADMIN","ROLE_MANAGER"})
*/
If I remember correctly, you always use { } in annotations, never [ ] (even if it's an index array). If you'r egetting an error about the annotation not being installed, make sure you have the use statement for it:
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
The php-annotations plugin in PhpStorm auto-adds this for me when I auto-complete the annotation :).
Cheers!
> btw ryan you have to update email just saw it in IsGranted.php :)
Ohh. I understand now! Yep, I'll probably have a lot of knpuniversity.com email addresses around in the code for a long time :p. But, that email does still work ;).
// composer.json
{
"require": {
"php": "^7.1.3",
"ext-iconv": "*",
"composer/package-versions-deprecated": "^1.11", // 1.11.99
"knplabs/knp-markdown-bundle": "^1.7", // 1.7.0
"knplabs/knp-paginator-bundle": "^2.7", // v2.8.0
"knplabs/knp-time-bundle": "^1.8", // 1.8.0
"nexylan/slack-bundle": "^2.0,<2.2.0", // v2.0.0
"php-http/guzzle6-adapter": "^1.1", // v1.1.1
"sensio/framework-extra-bundle": "^5.1", // v5.2.0
"stof/doctrine-extensions-bundle": "^1.3", // v1.3.0
"symfony/asset": "^4.0", // v4.1.4
"symfony/console": "^4.0", // v4.1.4
"symfony/flex": "^1.0", // v1.17.6
"symfony/framework-bundle": "^4.0", // v4.1.4
"symfony/lts": "^4@dev", // dev-master
"symfony/orm-pack": "^1.0", // v1.0.6
"symfony/security-bundle": "^4.0", // v4.1.4
"symfony/serializer-pack": "^1.0", // v1.0.1
"symfony/twig-bundle": "^4.0", // v4.1.4
"symfony/web-server-bundle": "^4.0", // v4.1.4
"symfony/yaml": "^4.0", // v4.1.4
"twig/extensions": "^1.5" // v1.5.2
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.0", // 3.0.2
"easycorp/easy-log-handler": "^1.0.2", // v1.0.7
"fzaninotto/faker": "^1.7", // v1.8.0
"symfony/debug-bundle": "^3.3|^4.0", // v4.1.4
"symfony/dotenv": "^4.0", // v4.1.4
"symfony/maker-bundle": "^1.0", // v1.7.0
"symfony/monolog-bundle": "^3.0", // v3.3.0
"symfony/phpunit-bridge": "^3.3|^4.0", // v4.1.4
"symfony/profiler-pack": "^1.0", // v1.0.3
"symfony/var-dumper": "^3.3|^4.0" // v4.1.4
}
}
How does ROLE_ADMIN look like in the database role column? Is it litterly a string called 'ROLE_ADMIN'? Or is ROLE_ADMIN a const somewhere?