2

I'm looking the best way to achieve "automatic" routing restriction to Ajax calls. Right now I'm doing as follow:

/**
 * @Secure(roles="IS_AUTHENTICATED_FULLY")
 * @Route("/someRoute", name="someRoute")
 * @Method("POST")
 */
public function eliminarFacturasAction(Request $request)
{
    $response['success'] = false;
    $status              = 400;

    if ($request->isXmlHttpRequest()) {
        // needs to set $response values and $status=200 all the time
    } else {
        // needs to handle the exception and return Json response
    }

    return new JsonResponse($response, $status ?: 200);
}

In order to avoid this could I use this instead?

 @Route("/someRoute", 
           name="routeName", 
           condition="request.headers.get('X-Requested-With') == 'XMLHttpRequest'"
 )

I'm using jQuery as only JS framework so XMLHttpRequest wont be a problem. What kind of exception will be trigger if route isn't executed through Ajax call? Can I catch it and show message to users? Or show some kind of 404 page?

I have found a similar question here but is not clear for me at all

Community
  • 1
  • 1
ReynierPM
  • 17,594
  • 53
  • 193
  • 363
  • Is there any good reason to limit the routes to XmlHttpRequests? Security-wise it can be circumvented in any case. – Gerry Jan 16 '15 at 15:12
  • uhm...I guess filters? – David Fregoli Jan 16 '15 at 15:16
  • @Gerry in my case yes, just a few ones (maybe 40 or more) due to requirements but keeping the code as I'm doing result noising and I think it could be a bad practice since I'm incurring in DRY – ReynierPM Jan 16 '15 at 15:19
  • @DavidFregoli I'm never worked before with filters, did you? Can post an example showing functionallity? – ReynierPM Jan 16 '15 at 15:19
  • I just wanted to point out that you would violate the HTTP spec by returning a 404 when not requesting via ajax and a valid response otherwise. – Gerry Jan 16 '15 at 15:21
  • @Gerry good point, how did you suggest me to handle this? – ReynierPM Jan 16 '15 at 15:22
  • Well personally I would not handle this at all :) maybe an access denied exception would be more appropriate. – Gerry Jan 16 '15 at 15:23
  • You could check for the ````X-Requested-With```` header in your controller and if not found throw an 412 error. When you use that often you could write [your own annotation](http://mmoreram.com/blog/2014/02/11/custom-controller-annotations/) to handle that. – Sander Toonen Jan 16 '15 at 15:29
  • @Xatoo this is kind of advanced for me but I'll take a look to it, I don't know how to hook in request on the Resolver :-( – ReynierPM Jan 16 '15 at 15:31

1 Answers1

5

You could do so in a kernel.request listener.

class DisallowNonXmlHttpRequestListener
{
    public function checkRequest(GetResponseEvent $event)
    {
        if (!$event->getRequest()->isXmlHttpRequest()) {
            throw new AccessDeniedHttpException();
        }
    }
}

And in your services config:

services:
    disallow_non_xml_http_request_listener:
        class: DisallowNonXmlHttpRequestListener
        tags: [{ name: kernel.event_listener, event: kernel.request, method: checkRequest }]
Gerry
  • 6,012
  • 21
  • 33
  • And how do I use? Is not clear to me if this will disallow all normal request or does not – ReynierPM Jan 16 '15 at 15:28
  • Yes this disallows all non-ajax requests. – Gerry Jan 16 '15 at 15:28
  • Wil not works for me since I do not need to disallow all the request on the complete site, just a few ones – ReynierPM Jan 16 '15 at 15:29
  • You could pass a list of routes to the listener and then check to see if the requested route matches. Same code as the login listener. – Cerad Jan 16 '15 at 15:43
  • @Cerad still not getting the whole point, could you post a piece of code just to see how that should work? I'm a bit lost at this point – ReynierPM Jan 17 '15 at 18:14