Symfony access control with variable inside route
Asked Answered
S

2

6

I'm defining security for my website in security.yml

    - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/ad/new, role: ROLE_USER  }
    - { path: ^/myAds, role: ROLE_USER  }
    - { path: ^/payments, role: ROLE_USER  }
    - { path: ^/pay, role: ROLE_USER  }

But I'm not sure how such a route would be added here:

mybundle_contact_advertiser:
   path:    /ad/{id}/contact
   defaults:   { _controller: MyBundle:Default:contactAdvertiser,id:null}

How is the id defined, considering I can't do it like so:

    - { path: ^/ad, role: ROLE_USER  }

As a route like

mybundle_ad:
    path:      /ad/{id}
    defaults:  { _controller: MyBundle:Default:viewAd ,id:null}

Would not work for unregistered users.

Subside answered 18/1, 2016 at 14:59 Comment(2)
you dont need to add every route to the security.yml there are wildcards wich will work just like in regex to scan which subpart of routes needs an authenticated user and which route doesn't ... and besides if you put a paramter in the middle of your route which can be null your route can be /ad/null/contact ... do you really want that ? Why not make the parameter optional if it can be nullArsenide
True, it shouldn't be null.Subside
C
4

I have two solutions for you.

First, add prefix to routes which need authentication and authorization. Then simply add that that prefix to your security.yml file. This way you do not need to add all routes manually.

Second, change your route to:

mybundle_contact_advertiser:
   path:    /ad/contact/{id}
   defaults:   { _controller: MyBundle:Default:contactAdvertiser}

Then add the following to your security.yml file:

- { path: ^/ad/contact/, role: ROLE_USER  }

But, if you do not want to change the route then check authorization inside your action

 $this->denyAccessUnlessGranted('ROLE_ADMIN', null, 'Unable to access this page!');

Or

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

Last but not least, you can use @Security annotation to secure your actions.

/**
 * @Security("has_role('ROLE_USER')")
 */
Christie answered 18/1, 2016 at 17:58 Comment(2)
Found out that ^/ad/(.+)/contact also works in the meantime. I knew most of your choices, and don't want to modify my route. The use of annotations doesn't really make sense as I don't really want to combine both annotations and .yml. It's either one or the other.Subside
@GeorgeIrimiciuc, thank you for sharing, I didn't know about using regex in routing security. Learnt something new today.Christie
P
11

All answers from @turdaliev-nursultan work.

But if you know that the {id} parameter will always be an integer, there's an additional possible answer.

You can edit the security.yml file and add the following rule to the access_control list :

- { path: ^/ad/[0-9]+/contact$, role: ROLE_USER }

The [0-9]+ part means any string made of one or more digits from 0 to 9.

Keep also in mind that using any url like http://example.com/ad/foo/contact, where the parameter is not an existing id, will lead to an http 404 error.

Piccalilli answered 21/3, 2017 at 16:10 Comment(1)
This might be invalid yaml you can use single quotes around the regex to prevent the yml parser from throwing an error when encountering the regexBelen
C
4

I have two solutions for you.

First, add prefix to routes which need authentication and authorization. Then simply add that that prefix to your security.yml file. This way you do not need to add all routes manually.

Second, change your route to:

mybundle_contact_advertiser:
   path:    /ad/contact/{id}
   defaults:   { _controller: MyBundle:Default:contactAdvertiser}

Then add the following to your security.yml file:

- { path: ^/ad/contact/, role: ROLE_USER  }

But, if you do not want to change the route then check authorization inside your action

 $this->denyAccessUnlessGranted('ROLE_ADMIN', null, 'Unable to access this page!');

Or

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

Last but not least, you can use @Security annotation to secure your actions.

/**
 * @Security("has_role('ROLE_USER')")
 */
Christie answered 18/1, 2016 at 17:58 Comment(2)
Found out that ^/ad/(.+)/contact also works in the meantime. I knew most of your choices, and don't want to modify my route. The use of annotations doesn't really make sense as I don't really want to combine both annotations and .yml. It's either one or the other.Subside
@GeorgeIrimiciuc, thank you for sharing, I didn't know about using regex in routing security. Learnt something new today.Christie

© 2022 - 2024 — McMap. All rights reserved.