Asked  7 Months ago    Answers:  5   Viewed   36 times

in Symfony2, is it possible to check if user is authenticated to access the URl he requested. What I want to do is, i dont want to allow a logged in user to go back to registration or login or recover password pages.

here is my security.yml:

    access_control:
    - { path: ^/signup/, roles: IS_AUTHENTICATED_ANONYMOUSLY && !IS_AUTHENTICATED_FULLY}
    - { path: ^/register/, roles: IS_AUTHENTICATED_ANONYMOUSLY && !IS_AUTHENTICATED_FULLY}
    - { path: ^/recover/, roles: IS_AUTHENTICATED_ANONYMOUSLY && !IS_AUTHENTICATED_FULLY}

but this is showing, access denied page to current user. So i think it would be nice if I can redirect the user to home page on such request, by checking if he is not allowed. Can I check by providing path that user is authenticated or not in listener?

    public function onKernelResponse(FilterResponseEvent $event)
    {
     $request = $event->getRequest();
     $path = $request->getPathInfo();

     if($this->container->get('security.context')->getToken() != null) {
       // To check if user is authenticated or anonymous
       if( ($this->container->get('security.context')->getToken() instanceof UsernamePasswordToken) &&
        ($this->container->get('security.context')->isGranted('IS_AUTHENTICATED_FULLY') == true) ) {
         // HOW TO CHECK PATH ?
        // set response to redirect to home page
      }
    }
  }

 Answers

33

The security.access_map service

The configuration of security.access_control is processed by ...

SecurityBundleDependencyInjectionSecurityExtension

... which creates RequestMatchers for the routes (path,hosts,ip,...) and then invokes the service's add() method with the matcher, the allowed roles and the channel (i.e. https ).

The service is usually used by i.e. the AccessListener.

You can use the security.access_map service to access the security.access_control parameters in your application.

The class used for the security.access_map service is defined by the parameter security.access_map.class and defaults to

SymfonyComponentSecurityHttpAccessMap ( implements AccessMapInterface )

You can use the parameter security.access_map.class to override the service with a custom class (must implement AccessMapInterface):

# i.e. app/config/config.yml

parameters:
    security.access_map.class: MyCustomAccessMap

How to access the service

The security.access_map service is a private service as you can see by it's definition here.

This means you can't request it from the container directly like this:

$this->container->get('security.access_map')

You will have to inject it into another service (i.e. a listener service) explicitly to be able to access it.


A listener example

services:
    my_listener:
        class: MyBundleMyListenerBundleEventListenerForbiddenRouteListener
        arguments: [ @security.access_map ]
        tags:      
            - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }

Then you can call the getPatterns() method to obtain the RequestMatchers, allowed roles and required channel from there.

namespace MyBundleMyListenerBundleEventListener;

use SymfonyComponentSecurityHttpAccessMapInterface;
use SymfonyComponentHttpKernelEventGetResponseEvent;

class ForbiddenRouteListener
{

    protected $accessMap;

    public function __construct(AccessMapInterface $access_map)
    {
        $this->accessMap = $access_map;
    }

    public function onKernelRequest(GetResponseEvent $event)
    {
        $request = $event->getRequest();
        $patterns = $this->accessMap->getPatterns($request);

        // ...
Wednesday, March 31, 2021
 
Gilko
answered 7 Months ago
28

you can get all the selected check box values using following code this might be helpful for you

var myArray = [];
var id = "";
var oTable = $("#example").dataTable();
$(".class1:checked", oTable.fnGetNodes()).each(function() {
    if (id != "") {
        id = id + "," + $(this).val();
    } else {
        id = $(this).val();
    }
});
Wednesday, March 31, 2021
 
van_folmert
answered 7 Months ago
90

Issue was with the priority order.

thanks @cerad for giving a clue about it

bin/console debug:event-dispatcher kernel.request

helped to solve the issue. i was using

tags:
        - { name: kernel.event_listener, event: kernel.response, method: onKernelResponse, priority: 10 }

in Services.yml and it had a conflict with the

getSubscribedEvents()

therefore i have removed tags and only kept

public static function getSubscribedEvents()
    {
        return array(
            KernelEvents::REQUEST  => array('onKernelRequest', 10),
        );
    }

then i moved authentication listener to the down by giving high priority to other two listeners as same as it was there in symfony 2.8

Thanks all for helping me out on this specially @Pie @Cerad and @BoShurik

Friday, May 28, 2021
 
Farnabaz
answered 5 Months ago
59

I ran into the same issue and found the following solution in the documentation: http://symfony.com/doc/current/book/testing.html#your-first-functional-test

To run your functional tests, the WebTestCase class bootstraps the kernel of your application. In most cases, this happens automatically. However, if your kernel is in a non-standard directory, you'll need to modify your phpunit.xml.dist file to set the KERNEL_DIR environment variable to the directory of your kernel:

<phpunit>
    <!-- ... -->
    <php>
        <server name="KERNEL_DIR" value="/path/to/your/app/" />
    </php>
    <!-- ... -->
</phpunit>

So check your phpunit.xml.dist configuration file and try to add the absolute path to your app-directory.

Hope it helps.

Friday, July 30, 2021
 
Bálint Molnár
answered 3 Months ago
94

Assuming that:

  • you inject security.context in your service

    public function __construct(SecurityContext $securityContext) {
      $this->securityContext = $securityContext;
    }
    
  • you are using FosUserBundle

  • I understood correctly your question :-)

you should be able to do:

$token = $this->securityContext->getToken();
if (empty($token)) {
    return [];
}
$user = $token->getUser();
if (empty($user)) {
    return [];
}
$roles = $user->getRoles();

Updates 2016/11/28

  1. Answer updated to pass the specific dependency instead of the whole container, as that is a bad practice (see comment by @Shady)
  2. Note that starting from Symfony 2.6, SecurityContext is deprecated, you should use TokenStorage instead.
Monday, October 4, 2021
 
Rob13
answered 3 Weeks ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :