1

I have an action that's meant to be accessed only through ajax. How can I make it give blank output when someone visits the url directly as http://site.com/controller/action? Is there a way that Zend can tell if it's an ajax call or direct url visit?

Edit: I found out about Zend's $this->getRequest()->isXmlHttpRequest(), but I wonder if this can be trusted enough?

jblue
  • 4,390
  • 4
  • 46
  • 79

2 Answers2

4

There's no way of reliably telling an AJAX request and any other kind of request apart, so no you can't block non-AJAX access.

GordonM
  • 31,179
  • 15
  • 87
  • 129
  • http://stackoverflow.com/questions/2579254/php-does-serverhttp-x-requested-with-exist-or-not/2579271#2579271 explains it quite well. Proxy servers can screw with the headers, and some XHR engines didn't send it in the first place. – GordonM Mar 10 '11 at 09:32
  • What is an XHR engine? A jquery library, or something different? – jblue Mar 10 '11 at 09:47
  • Most common libraries (jquery, dojo, mootools, yui etc) include AJAX functionality that use XmlHttpRequest for doing AJAX. This is what I mean by XHR engine – GordonM Mar 10 '11 at 11:15
1

If you're using jQuery, you can check it like:

if(empty($_SERVER['HTTP_X_REQUESTED_WITH']) || strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) != 'xmlhttprequest') {
    return die('No direct access allowed.');
}
fabrik
  • 14,094
  • 8
  • 55
  • 71
  • @fabrik Yes, I'm using Jquery. So is this method guaranteed to work with all browsers? I mean it depends on the javascript library, not the browser? – jblue Mar 10 '11 at 09:26
  • The x-requested-with header can be spoofed, or it could conceivably be omitted or set to a different value than expected for some XHR engines. This isn't 100% reliable and could block access from legit AJAX requests without preventing non-AJAX access for someone who was determined enough to spoof the headers. – GordonM Mar 10 '11 at 09:26
  • Yup. AFAIK jQuery handling this header properly, so you can safely rely on these lines. – fabrik Mar 10 '11 at 09:27
  • This header is sent by the client and therefore can't be fully trusted. Also, the code below is wrong; why check if a key is empty--which will trigger an error if it doesn't exists--and then test if it is "xmlhttprequest"? – seriousdev Mar 10 '11 at 09:28
  • @sexysprout: the code above is working fine. with or without direct access. – fabrik Mar 10 '11 at 09:30
  • @fabrik: The consequences of this particular test breaking are a) legit AJAX requests are rejected and b) ones you are trying to block get through anyway. The unintended consequence of a) makes the attempt at blocking not worth it, especially when you take b) into account. See also http://stackoverflow.com/questions/2579254/php-does-serverhttp-x-requested-with-exist-or-not/2579271#2579271 – GordonM Mar 10 '11 at 09:31
  • Thanks for the explanation and tell me about a better solution. – fabrik Mar 10 '11 at 09:36
  • 2
    @fabric I would tend to wonder why such a restriction is necessary. If it's for security then you'd be better off making your Ajax scripts do the same security checks as the rest of your project such as only returning output if a valid user is logged in – GordonM Mar 10 '11 at 09:53
  • @Gordon: this would be nice (+1), but we don't know too much about OP's scenario. Maybe the AJAX is only serving some kind of navigation system i.e. serving pages based on requests. In that case you cannot tie this kind of restriction only for logged in users. – fabrik Mar 10 '11 at 09:58