Apache Zeta Components Manual :: File Source for filter.php

Source for file filter.php

Documentation is available at filter.php

  1. <?php
  2. /**
  3.  *
  4.  * Licensed to the Apache Software Foundation (ASF) under one
  5.  * or more contributor license agreements.  See the NOTICE file
  6.  * distributed with this work for additional information
  7.  * regarding copyright ownership.  The ASF licenses this file
  8.  * to you under the Apache License, Version 2.0 (the
  9.  * "License"); you may not use this file except in compliance
  10.  * with the License.  You may obtain a copy of the License at
  11.  * 
  12.  *   http://www.apache.org/licenses/LICENSE-2.0
  13.  * 
  14.  * Unless required by applicable law or agreed to in writing,
  15.  * software distributed under the License is distributed on an
  16.  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  17.  * KIND, either express or implied.  See the License for the
  18.  * specific language governing permissions and limitations
  19.  * under the License.
  20.  *
  21.  * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
  22.  * @version //autogentag//
  23.  * @filesource
  24.  * @package MvcAuthenticationTiein
  25.  */
  26.  
  27. /**
  28.  * This class provides a filter that applications can use for authentication.
  29.  *
  30.  * Through the $options argument to the controller you can configure many
  31.  * aspects of this filter. By default a few settings are made that setup table
  32.  * names and fields names, as well as names of variables under which certain
  33.  * bits of the filter will be available in the controller's actions. The filter
  34.  * needs to be integrated in both the applications configuration (through an
  35.  * implementation of ezcMvcDispatcherConfiguration) as well as in the
  36.  * controller handling authentication actions. Please refer to the tutorial on
  37.  * how to do this.
  38.  *
  39.  * Some of the defaults provided in this filter can easily be changed by
  40.  * inheriting. For example if you want to change the password generation
  41.  * algorithm you need to override generatePassword(). Another example is when
  42.  * you want other authentication methods besides session and database. In that
  43.  * case setupAuth() needs to be overridden in an inherited class.
  44.  *
  45.  * @package MvcAuthenticationTiein
  46.  * @version //autogentag//
  47.  * @mainclass
  48.  */
  49. {
  50.     /**
  51.      * Contains the filter options object
  52.      *
  53.      * @var ezcMvcAuthenticationFilterOptions 
  54.      */
  55.     private $options;
  56.  
  57.     /**
  58.      * Constructs a new ezcMvcAuthenticationFilter object
  59.      *
  60.      * @param ezcMvcAuthenticationFilterOptions $options 
  61.      */
  62.     function __constructezcMvcAuthenticationFilterOptions $options null )
  63.     {
  64.         $this->options $options === null new ezcMvcAuthenticationFilterOptions($options;
  65.     }
  66.  
  67.     /**
  68.      * Sets a new options object
  69.      *
  70.      * @param ezcMvcAuthenticationFilterOptions $options 
  71.      */
  72.     public function setOptionsezcMvcAuthenticationFilterOptions $options )
  73.     {
  74.         $this->options $options;
  75.     }
  76.  
  77.     /**
  78.      * Returns the currently set options
  79.      *
  80.      * @return ezcMvcAuthenticationFilterOptions 
  81.      */
  82.     public function getOptions()
  83.     {
  84.         return $this->options;
  85.     }
  86.  
  87.     /**
  88.      * Returns the value of the property $name.
  89.      *
  90.      * @throws ezcBasePropertyNotFoundException
  91.      *          if the property $name does not exist
  92.      * @param string $name 
  93.      * @ignore
  94.      */
  95.     public function __get$name )
  96.     {
  97.         switch $name )
  98.         {
  99.             case 'options':
  100.                 return $this->options;
  101.                 break;
  102.         }
  103.         throw new ezcBasePropertyNotFoundException$name );
  104.     }
  105.  
  106.     /**
  107.      * Sets the property $name to $value.
  108.      *
  109.      * @throws ezcBasePropertyNotFoundException
  110.      *          if the property $name does not exist
  111.      * @throws ezcBaseValueException
  112.      *          if $value is not accepted for the property $name
  113.      * @param string $name 
  114.      * @param mixed $value 
  115.      * @ignore
  116.      */
  117.     public function __set$name$value )
  118.     {
  119.         switch $name )
  120.         {
  121.             case 'options':
  122.                 if !$value instanceof ezcMvcAuthenticationFilterOptions ) )
  123.                 {
  124.                     throw new ezcBaseValueException'options'$value'instanceof ezcMvcAuthenticationFilterOptions' );
  125.                 }
  126.                 $this->options $value;
  127.                 break;
  128.  
  129.             default:
  130.                 throw new ezcBasePropertyNotFoundException$name );
  131.         }
  132.     }
  133.  
  134.     /**
  135.      * Returns true if the property $name is set, otherwise false.
  136.      *
  137.      * @param string $name 
  138.      * @return bool 
  139.      * @ignore
  140.      */
  141.     public function __isset$name )
  142.     {
  143.         switch $name )
  144.         {
  145.             case 'options':
  146.                 return true;
  147.  
  148.             default:
  149.                 return false;
  150.         }
  151.     }
  152.  
  153.     /**
  154.      * This method sets up the authentication mechanism.
  155.      *
  156.      * By default it uses database and session storage only. If you want to do
  157.      * more complex things, the best way would be to inherit from this class
  158.      * and override this method. It takes a user name and password, but those
  159.      * can be empty if your overridden class does not require them. This method
  160.      * will also be called with $user and $password being NULL in case the
  161.      * filter needs to check whether a user is already logged in. In this case,
  162.      * the session should be checked.
  163.      *
  164.      * @param string $user 
  165.      * @param string $password 
  166.      *
  167.      * @return ezcAuthentication 
  168.      */
  169.     protected function setupAuth$user null$password null )
  170.     {
  171.         $database new ezcAuthenticationDatabaseInfo(
  172.             $this->options->database,
  173.             $this->options->tableName,
  174.             array$this->options->userIdField$this->options->passwordField )
  175.         );
  176.         $databaseFilter new ezcAuthenticationDatabaseFilter$database );
  177.  
  178.         // use the options object when creating a new Session object
  179.         $options new ezcAuthenticationSessionOptions();
  180.         $options->validity 86400;
  181.         $options->idKey $this->options->sessionUserIdKey;
  182.         $options->timestampKey $this->options->sessionTimestampKey;
  183.  
  184.         $session new ezcAuthenticationSession$options );
  185.         $session->start();
  186.  
  187.         if $user === null )
  188.         {
  189.             $user $session->load();
  190.             $password null;
  191.         }
  192.  
  193.         $credentials new ezcAuthenticationPasswordCredentials$user$this->hashPassword$password ) );
  194.         $authentication new ezcAuthentication$credentials );
  195.         $authentication->session $session;
  196.         $authentication->addFilter$databaseFilter );
  197.  
  198.         return $authentication;
  199.     }
  200.  
  201.     /**
  202.      * Returns the username associated with the user ID as stored in the session.
  203.      *
  204.      * This method could be a likely candidate to override as well, although it
  205.      * is as configurable as possible. If usernames are not stored in the
  206.      * database, this method needs to be overridden as well. The method's
  207.      * return value is used by the setVars() method to add user ID and user
  208.      * name to the session so that the application can use this data.
  209.      *
  210.      * @return string 
  211.      */
  212.     protected function fetchUserName()
  213.     {
  214.         if isset$_SESSION[$this->options->sessionUserIdKey) )
  215.         {
  216.             $q ezcDbInstance::get()->createSelectQuery();
  217.             $q->select'*' )
  218.               ->from$this->options->tableName )
  219.               ->where$q->expr->eq$this->options->userIdField$q->bindValue$_SESSION[$this->options->sessionUserIdKey) ) );
  220.             $s $q->prepare();
  221.             $s->execute();
  222.             $r $s->fetchAll();
  223.  
  224.             return $r[0][$this->options->userNameField];
  225.         }
  226.         return null;
  227.     }
  228.  
  229.     /**
  230.      * This method sets the user ID and user name variables as part of the
  231.      * $request and $result objects.
  232.      *
  233.      * This method should be called by the application's runRequestFilters()
  234.      * and runResultFilters() methods to add authentication information to the
  235.      * request and/or result. The method also makes the authentication filter
  236.      * available to the controller actions so it is important that it is called
  237.      * in both filters, and preferably as the first method call.
  238.      *
  239.      * The variable names that contain the user ID and user name can be
  240.      * configured through the $options object that is passed to the contructor.
  241.      *
  242.      * @param ezcMvcRequest|ezcMvcResult
  243.      */
  244.     public function setVars$requestOrResult )
  245.     {
  246.         $requestOrResult->variables[$this->options->varNameFilter$this;
  247.         if isset$_SESSION[$this->options->sessionUserIdKey) )
  248.         {
  249.             $requestOrResult->variables[$this->options->varNameUserId$_SESSION[$this->options->sessionUserIdKey];
  250.             $requestOrResult->variables[$this->options->varNameUserNameself::fetchUserName();
  251.         }
  252.     }
  253.  
  254.     /**
  255.      * Sets up the authentication mechanism to be used for routes that do not require authentication.
  256.      *
  257.      * This method is meant to be run from the runRequestFilters() method for
  258.      * the routes that do not require authentication or deal with logging in,
  259.      * logging out and registering users. It sets up the session so that the
  260.      * controller has access to the authentication data.
  261.      *
  262.      * @param ezcMvcRequest $request 
  263.      */
  264.     public function runAuthCheckLoggedInezcMvcRequest $request )
  265.     {
  266.         $auth self::setupAuth();
  267.         $auth->run();
  268.     }
  269.  
  270.     /**
  271.      * Sets up the authentication mechanism to be used for routes that do require authentication.
  272.      *
  273.      * This method is meant to be run from the runRequestFilters() method for
  274.      * the routes that do require an authenticated user.  It sets up the
  275.      * session so that the controller has access to the authentication data.
  276.      * The method will return an internal redirect return that redirects to the
  277.      * configured loginRequiredUri. That Uri's controller and action needs to
  278.      * present the login form.
  279.      *
  280.      * @param ezcMvcRequest $request 
  281.      */
  282.     public function runAuthRequiredFilter$request )
  283.     {
  284.         $auth self::setupAuth();
  285.         if !$auth->run() )
  286.         {
  287.             $status $auth->getStatus();
  288.             $request->variables['ezcAuth_redirUrl'$request->uri;
  289.             $request->variables['ezcAuth_reasons']  $status;
  290.  
  291.             $request->uri $this->options->loginRequiredUri;
  292.             return new ezcMvcInternalRedirect$request );
  293.         }
  294.     }
  295.  
  296.     /**
  297.      * Method to be called from the controller's login action to log a user in.
  298.      *
  299.      * @param ezcMvcRequest $request 
  300.      * @param string        $user 
  301.      * @param string        $password 
  302.      */
  303.     public function loginezcMvcRequest $request$user$password )
  304.     {
  305.         return $this->setupAuth$user$password );
  306.     }
  307.  
  308.     /**
  309.      * Method to be called from the controller's logout action to log a user out.
  310.      *
  311.      * @param ezcMvcRequest $request 
  312.      */
  313.     public function logoutezcMvcRequest $request )
  314.     {
  315.         $options new ezcAuthenticationSessionOptions();
  316.         $options->validity 86400;
  317.  
  318.         $session new ezcAuthenticationSession$options );
  319.         $session->start();
  320.         unset$_SESSION[$this->options->sessionUserIdKey);
  321.         $session->destroy();
  322.     }
  323.  
  324.     /**
  325.      * Checks whether a user exists in the database.
  326.      *
  327.      * This method should be called from the "register" action to see if the
  328.      * requested user ID has already been registered or not.
  329.      *
  330.      * @param string $username 
  331.      * @return bool 
  332.      */
  333.     public function checkUserExists$username )
  334.     {
  335.         $q ezcDbInstance::get()->createSelectQuery();
  336.         $q->select$this->options->userIdField )
  337.           ->from$this->options->tableName )
  338.           ->where$q->expr->eq(
  339.                 $this->options->userIdField,
  340.                 $q->bindValue$username ) )
  341.             );
  342.         $s $q->prepare();
  343.         $s->execute();
  344.         $r $s->fetchAll();
  345.  
  346.         return count$r == );
  347.     }
  348.  
  349.     /**
  350.      * Returns a generated basic password depending on the $username.
  351.      *
  352.      * This method is typically called from the "register" action after a user
  353.      * ID has been checked for existance.
  354.      *
  355.      * @param string $username 
  356.      * @return string 
  357.      */
  358.     public function generatePassword$username )
  359.     {
  360.         // generate password
  361.         mt_srand(
  362.             base_convertsubstrmd5$username )0)3610 *
  363.             microtimetrue )
  364.         );
  365.         $a base_convertmt_rand()1036 );
  366.         $b base_convertmt_rand()1036 );
  367.         $password substr$b $a1);
  368.  
  369.         return $password;
  370.     }
  371.  
  372.     /**
  373.      * Returns the hashed version of the clear text password
  374.      *
  375.      * @param string $password 
  376.      * @return string 
  377.      */
  378.     protected function hashPassword$password )
  379.     {
  380.         return md5$password );
  381.     }
  382.  
  383.     /**
  384.      * Creates an entry in the user database table for $username and $password.
  385.      *
  386.      * This method creates a user in the configured user table (through the
  387.      * options for this class). You can specify extra information as a
  388.      * key->value pair array as $extraInfo.  This method does *not* check
  389.      * whether a user already exists.
  390.      *
  391.      * @param string $username 
  392.      * @param string $password 
  393.      * @param array(string=>mixed) $extraInfo 
  394.      */
  395.     public function createUser$username$passwordarray $extraInfo )
  396.     {
  397.         $q ezcDbInstance::get()->createInsertQuery();
  398.         $q->insertInto$this->options->tableName )
  399.           ->set$this->options->userIdField$q->bindValue$username ) )
  400.           ->set$this->options->passwordField$q->bindValue$this->hashPassword$password ) ) );
  401.         foreach $extraInfo as $key => $value )
  402.         {
  403.             $q->set$key$q->bindValue$value ) );
  404.         }
  405.         $s $q->prepare();
  406.         $s->execute();
  407.     }
  408.  
  409.     /**
  410.      * Checks the status from the authentication run and adds the reasons as
  411.      * variable to the $result.
  412.      *
  413.      * This method uses the information that is set by the
  414.      * runAuthRequiredFilter() filter to generate an user-readable text of the
  415.      * found $reasons and sets these as the variable ezcAuth_reasons in
  416.      * the $result. You can supply your own mapping from status codes to
  417.      * messages, but a default is provided. Please refer to the Authentication
  418.      * tutorial for information about status codes.
  419.      *
  420.      * @param ezcMvcResult $result 
  421.      * @param array(string) $reasons 
  422.      * @param array(string=>array(int=>string) $errorMap 
  423.      */
  424.     function processLoginRequiredezcMvcResult $res$reasons$errorMap null )
  425.     {
  426.         $reasonText array();
  427.  
  428.         if $errorMap === null )
  429.         {
  430.             $errorMap array(
  431.                 'ezcAuthenticationDatabaseFilter' => array(
  432.                     ezcAuthenticationHtpasswdFilter::STATUS_USERNAME_INCORRECT => 'Incorrect or no credentials provided.',
  433.                     ezcAuthenticationHtpasswdFilter::STATUS_PASSWORD_INCORRECT => 'Incorrect or no credentials provided.'
  434.                 ),
  435.                 'ezcAuthenticationSession' => array(
  436.                     ezcAuthenticationSession::STATUS_EMPTY => 'No session',
  437.                     ezcAuthenticationSession::STATUS_EXPIRED => 'Session expired'
  438.                 ),
  439.             );
  440.         }
  441.  
  442.         foreach $reasons as $line )
  443.         {
  444.             list$key$value each$line );
  445.             $reasonText[$errorMap[$key][$value];
  446.         }
  447.         $res->variables['ezcAuth_reasons']  $reasonText;
  448.     }
  449.  
  450.     /**
  451.      * Returns either an internal or external redirect depending on whether the
  452.      * user authenticated succesfully.
  453.      *
  454.      * This method is run from the "login" action just after login() has been
  455.      * called. It takes the $authentication object, the $request and the form
  456.      * provided $redirUrl. It redirects upon failure to the configured
  457.      * loginRequiredUri and upon succes to the provided $redirUrl. The
  458.      * redirection happens by returning an ezcMvcInternalRedirect or
  459.      * ezcMvcResult with a ezcMvcExternalRedirect status.
  460.      *
  461.      * @param ezcAuthentication $authentication 
  462.      * @param ezcMvcRequest     $request 
  463.      * @param string            $redirUrl 
  464.      * @return ezcMvcInternalRedirect|ezcMvcResult
  465.      */
  466.     function returnLoginRedirectezcAuthentication $authenticationezcMvcRequest $request$redirUrl )
  467.     {
  468.         if !$authentication->run() )
  469.         {
  470.             $request clone $request;
  471.             $status $authentication->getStatus();
  472.             $request->variables['ezcAuth_redirUrl'$redirUrl;
  473.             $request->variables['ezcAuth_reasons']  $status;
  474.  
  475.             $request->uri $this->options->loginRequiredUri;
  476.             return new ezcMvcInternalRedirect$request );
  477.         }
  478.  
  479.         $res new ezcMvcResult;
  480.         $res->status new ezcMvcExternalRedirect$redirUrl );
  481.         return $res;
  482.     }
  483.  
  484.     /**
  485.      * Returns an external redirect depending to the configured logoutUri.
  486.      *
  487.      * This method is run from the "logout" action just after logout() has been
  488.      * called. It takes the $request object as parameter although this is not
  489.      * used by this default implementation.  The method returns an
  490.      * ezcMvcRequest result with a ezcMvcExternalRedirect status to redirect to
  491.      * the configured logoutUri.
  492.      *
  493.      * @param ezcMvcRequest     $request 
  494.      * @return ezcMvcResult 
  495.      */
  496.     function returnLogoutRedirectezcMvcRequest $request )
  497.     {
  498.         $res new ezcMvcResult;
  499.         $res->status new ezcMvcExternalRedirect$this->options->logoutUri );
  500.         return $res;
  501.     }
  502. }
  503. ?>
Documentation generated by phpDocumentor 1.4.3