views:

699

answers:

2

I'm developing a CakePHP site for which I've just enabled VAS authentication using a .htaccess file:

AuthType VAS

AuthVasUseBasic On
AuthVasRemoteUserMap local

Require valid-user

I'd expect to be able to find out who was logged in by using $_SERVER['REMOTE_USER'], but I'm finding that the key is missing from the $_SERVER structure: all that's there is $_SERVER['REDIRECT_REMOTE_USER']. In fact, the whole structure is full of keys with the REDIRECT_ prefix:

echo var_dump($_SERVER);
array(52) {
["REDIRECT_REDIRECT_REDIRECT_SCRIPT_URL"]=>  string(37) "/cake_1_2/feedbacks/edit/6" 
["REDIRECT_REDIRECT_REDIRECT_SCRIPT_URI"]=>  string(55) "http://test/cake_1_2/feedbacks/edit/6"
["REDIRECT_REDIRECT_REDIRECT_STATUS"]=>  string(3) "200" 
["REDIRECT_REDIRECT_SCRIPT_URL"]=>  string(37) "/cake_1_2/feedbacks/edit/6" 
["REDIRECT_REDIRECT_SCRIPT_URI"]=>  string(55) "http://test/cake_1_2/feedbacks/edit/6" 
["REDIRECT_REDIRECT_STATUS"]=>  string(3) "200" 
["REDIRECT_SCRIPT_URL"]=>  string(37) "/cake_1_2/feedbacks/edit/6" 
["REDIRECT_SCRIPT_URI"]=>  string(55) "http://test/cake_1_2/feedbacks/edit/6" 
["REDIRECT_HANDLER"]=>  string(8) "php5-cgi"
["REDIRECT_STATUS"]=>  string(3) "200" 
["SCRIPT_URL"]=>  string(37) ...
["REDIRECT_REMOTE_USER"]=>  string(9) "andygeers"
... 
}

I'm not exactly sure what's going on! This is generated first thing in a POST request, and it's not doing a redirect on this particular request.

Is this related to CakePHP, or just a general PHP issue? Any ideas what's going on? I've found quite a few pages on the internet now which suggest REDIRECT_REMOTE_USER is normal/common as a place to find this value, but nobody seems to know why!

+1  A: 

This is a general PHP thing. Some frameworks redirect pages internally according to their routing policies. If you redirect outside of a framework you'll get the same result. A direct access to a page outside of a framework will give you the names you initially expected. I do notice though that in CodeIgniter you get $_SERVER['REMOTE_USER'] and no redirect. So it is dependent on which framework you use.

So it's probably best to check for both if you are unsure whether or not there's a redirect happening.

I also notice you are using AuthVasUseBasic On. If you are using this you should also check for the basic user auth variable $_SERVER['USERNAME'] IIRC

Svenito
+2  A: 

Apache is adding those REDIRECT_ prefixes so that scripts can better handle what has happened. For my application I have written a function to deal with this. In my case it's a method on a class, but you can easily turn it into a global function.

class MyClass {
    /** @var integer How deep the redirect layers of Apache go. -1 means not set. */
    private $redirectLevel = -1;

    /**
     * Get an environment variable with all the REDIRECT_ prefixes stripped off
     */
    private function getEnv($var)
    {
     // Find out how deep the redirect goes
     if ($this->redirectLevel == -1) {
      reset($_SERVER);
      $key = key($_SERVER);
      $this->redirectLevel = substr_count($key, 'REDIRECT_');
     }

     $result = '';
     $prefix = '';
     for ($i = 0; $i < $this->redirectLevel + 1; $i++) {
      if (isset($_SERVER[$prefix . $var])) {
       $result = $_SERVER[$prefix . $var];
      }
      $prefix .= 'REDIRECT_';
     }
     return $result;
    }
}

EDIT: The above function returns the contents of the variable that has the most REDIRECT_ prefixes, which is usually what you want. If Apache would not prefix the variables then that is what you'd get. The contents of the variables can change depending on the number of prefixes. After all, Apache adds the prefix so it does not overwrite the old value.

For example, on my site I use mod_ssl to do client authentication with client SSL certificates. The certificate subject (containing the user's e-mail address) is stored in the SSL_CLIENT_S_DN variable. With Apache prefixing, this will come out as:

$_SERVER['REDIRECT_REDIRECT_SSL_CLIENT_S_DN'] // string containing the subject
$_SERVER['REDIRECT_SSL_CLIENT_S_DN'] // exists, but empty
// $_SERVER['SSL_CLIENT_S_DN'] does not exist

The getEnv() function I wrote above will return the top one.

Sander Marechal
Will all of the values be gauranteed to be the same, regardless of how many `REDIRECT_` prefixes they contain?
andygeers
No, they can change. See my updated answer.
Sander Marechal