Author: Alexandru Stanoi Date: 2007-05-04 16:58:45 +0200 (Fri, 04 May 2007) New Revision: 5060
Log: - Tie-in containing the Database filter from the Authentication component. Added: experimental/AuthenticationDatabaseTiein/ experimental/AuthenticationDatabaseTiein/CREDITS experimental/AuthenticationDatabaseTiein/ChangeLog experimental/AuthenticationDatabaseTiein/DEPS experimental/AuthenticationDatabaseTiein/DESCRIPTION experimental/AuthenticationDatabaseTiein/design/ experimental/AuthenticationDatabaseTiein/design/design.txt experimental/AuthenticationDatabaseTiein/design/requirements.txt experimental/AuthenticationDatabaseTiein/docs/ experimental/AuthenticationDatabaseTiein/docs/tutorial.txt experimental/AuthenticationDatabaseTiein/docs/tutorial/ experimental/AuthenticationDatabaseTiein/docs/tutorial/tutorial_database.php experimental/AuthenticationDatabaseTiein/src/ experimental/AuthenticationDatabaseTiein/src/authentication_database_autoload.php experimental/AuthenticationDatabaseTiein/src/filters/ experimental/AuthenticationDatabaseTiein/src/filters/database/ experimental/AuthenticationDatabaseTiein/src/filters/database/database_filter.php experimental/AuthenticationDatabaseTiein/src/filters/database/database_info.php experimental/AuthenticationDatabaseTiein/src/filters/database/database_options.php experimental/AuthenticationDatabaseTiein/tests/ experimental/AuthenticationDatabaseTiein/tests/filters/ experimental/AuthenticationDatabaseTiein/tests/filters/database/ experimental/AuthenticationDatabaseTiein/tests/filters/database/database_test.php experimental/AuthenticationDatabaseTiein/tests/suite.php Added: experimental/AuthenticationDatabaseTiein/CREDITS =================================================================== --- experimental/AuthenticationDatabaseTiein/CREDITS 2007-05-04 14:55:21 UTC (rev 5059) +++ experimental/AuthenticationDatabaseTiein/CREDITS 2007-05-04 14:58:45 UTC (rev 5060) @@ -0,0 +1,16 @@ +CREDITS +======= + +eZ components team +------------------ + +- Sergey Alexeev +- Jan Borsodi +- Raymond Bosman +- Frederik Holljen +- Kore Nordmann +- Derick Rethans +- Vadym Savchuk +- Tobias Schlitt +- Sebastian Bergmann +- Alexandru Stanoi Added: experimental/AuthenticationDatabaseTiein/ChangeLog =================================================================== --- experimental/AuthenticationDatabaseTiein/ChangeLog 2007-05-04 14:55:21 UTC (rev 5059) +++ experimental/AuthenticationDatabaseTiein/ChangeLog 2007-05-04 14:58:45 UTC (rev 5060) @@ -0,0 +1,4 @@ +1.0beta1 - [RELEASEDATE] +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- Initial release of this package. Added: experimental/AuthenticationDatabaseTiein/DEPS =================================================================== --- experimental/AuthenticationDatabaseTiein/DEPS 2007-05-04 14:55:21 UTC (rev 5059) +++ experimental/AuthenticationDatabaseTiein/DEPS 2007-05-04 14:58:45 UTC (rev 5060) @@ -0,0 +1,2 @@ +Datebase: 1.1.4 +Authentication: 1.0 Added: experimental/AuthenticationDatabaseTiein/DESCRIPTION =================================================================== --- experimental/AuthenticationDatabaseTiein/DESCRIPTION 2007-05-04 14:55:21 UTC (rev 5059) +++ experimental/AuthenticationDatabaseTiein/DESCRIPTION 2007-05-04 14:58:45 UTC (rev 5060) @@ -0,0 +1,3 @@ +The purpose of the Authentication component is to provide support for different +means of identification and authentication of users using different providers and +protocols. Added: experimental/AuthenticationDatabaseTiein/design/design.txt =================================================================== --- experimental/AuthenticationDatabaseTiein/design/design.txt 2007-05-04 14:55:21 UTC (rev 5059) +++ experimental/AuthenticationDatabaseTiein/design/design.txt 2007-05-04 14:58:45 UTC (rev 5060) @@ -0,0 +1,242 @@ +eZ Components - Authentication, Design +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +:Author: Alexandru Stanoi +:Revision: $Revision: $ +:Date: $Date: $ + + +Introduction +============ + +Description +----------- + +The purpose of the Authentication component is to provide support for different +means of identification and authentication of users using different providers and +protocols. + + +Design +====== + +Base classes +------------ + +ezcAuthentication + Container for authentication filters. Runs all the specified filters in + sequence to check if all succeed or if any filter fails. + +ezcAuthenticationFilter + Abstract class which is a base class for all authentication filters. It can + be extended to create new filters. + +ezcAuthenticationCredentials + A structure which holds basic information to authenticate the user. + Developers can extend this class to include additional credentials. + + +Authentication filters +---------------------- + +A list of supported authentication filters (plug-ins). This list can be +extended by developers or by us in future releases: + +ezcAuthenticationSessionFilter + Support for storing authentication information in the session. + +ezcAuthenticationGroupFilter + Support for grouping two or more filters, where only one filter needs to + succeed for the group to succeed. + +ezcAuthenticationHtpasswdFilter + Handles authentication using a htpasswd file. Basic filter and not too secure + as the htpasswd file can be accessible to someone who has access to the + server. Should not be employed on critical application. It is used mostly as + an example. + +ezcAuthenticationTokenFilter + Handles authentication based on a server generated code. Similar to the + Ticket filter, but the code is not saved in a database, but it is generated + on every request. One use of such a filter is for CAPTCHA tests, or for + challenge responses to a server code with a user code (usually banks require + users to use code calculators). + +ezcAuthenticationLdapFilter + Handles authentication using an LDAP directory. + +ezcAuthenticationOpenidFilter + Handles authentication using the OpenID protocol. + +ezcAuthenticationTypekeyFilter + Handles authentication using the TypeKey protocol. + + +Extended filters +---------------- + +A list of supported authentication filters (plug-ins). These filters will be +implemented in a tie-in component as they depend on other components: + +ezcAuthenticationDatabaseFilter + Handles authentication using a database, by specifying the database name, + user and password to use the database, table name, fields to check and + whether to use encryption for each field or not. + +ezcAuthenticationTicketFilter + Handles authentication using a token (server generated code). It is basically + a database filter with only one field, and with deletion of the record after + authentication. One use of such a filter is for sending confirmation emails + to the user. + + +Implementation +============== + +ezcAuthentication +----------------- + +Container for AuthenticationFilters. Contains these methods: + +run() + Runs through all the filters in their sequence. If all filters succeed, then + it will return true, otherwise returns false, and the $status property of the + authentication object will contain the statuses of all filters until that + moment. + +addFilter() + Adds a filter to the list of authentication filters. + +Contains these properties: + +status + A list of the error codes until the current moment (for example + ezcAuthenticationLdapFilter::STATUS_PASSWORD_INCORRECT). + + +ezcAuthenticationFilter +----------------------- + +Abstract class which is a base class for all authentication filters. It can +be extended to create new filters. It contains these abstract methods: + +run() + Executes the filter authentication. Can return different statuses which are + used by the ezcAuthentication object to decide if the next filter is needed + to run or if the authentication process failed at the current filter. + + +ezcAuthenticationSessionFilter +------------------------------ + +Support for storing authentication information in the session. Uses a specified +key in the session to store if the user is authenticated or not. Cases: + +Login by starting a new session + Authentication will accept the new session and initiate authentication using + the other defined filters. + +Login by using an existing session + Authentication will check if the existing session is within the expiring + period (defined by the developer of the application using the session + options). If the session expired, then it will create a new session (new + session ID) and initiate authentication using the other defined filters. If + the session did not expire, then it will grant access bypassing the other + defined filters. + +Login by using another session ID than the one stored + Probably an attack. It will warn about the conflict, generate a new ID and + initiate the authentication using the other defined filters. + + +ezcAuthenticationDatabaseFilter +------------------------------- + +Implemented in a tie-in component as it depends on the DatabaseSchema and +Database components. Works on an instance of ezcDbInstance. Options to specify +include the table name and the user and password fields names. + + +ezcAuthenticationTicketFilter +----------------------------- + +Extends the ezcAuthenticationDatabaseFilter class. Implemented in a tie-in +component as it depends on the Database and DatabaseSchema components. + + +ezcAuthenticationTokenFilter +---------------------------- + +The token will be generated by a random function that the developer specifies. +This filter just compares this token with the token entered by the user, using +a specified function. + + +Examples +======== + +Htpasswd authentication +----------------------- + +The following example shows how to authenticate against an htpasswd file: :: + + // get $user and $password from POST variables + $credentials = new ezcAuthenticationPasswordCredentials( $user, $password ); + $authentication = new ezcAuthentication( $credentials ); + + $authentication->addFilter( new ezcAuthenticationHtpasswdFilter( + '/home/root/.htpasswd' ) ); + + if ( !$authentication->run() ) + { + // return the status of the authentication, + // for example ezcAuthenticationHtpasswdFilter::STATUS_PASSWORD_INCORRECT + $status = $authentication->getStatus(); + + // use the returned status to provide the user with a friendly error + // message, such as "The password you entered is incorect. Please try + // again.", and don't allow the user to see the protected content. + } + else + { + // allow the user to see the protected content + } + + +Database authentication +----------------------- + +The following example shows how to authenticate using a database, and using the +session to cache the authentication between requests: :: + + // get $user and $password from POST variables or from session + $credentials = new ezcAuthenticationPasswordCredentials( $user, $password ); + $authentication = new ezcAuthentication( $credentials ); + $authentication->session = new ezcAuthenticationSessionFilter(); + + $db = new ezcAuthenticationDatabaseInfo( ezcDbInstance::get(), + 'users', array( 'user', 'password' ) ); + $authentication->addFilter( new ezcAuthenticationDatabaseFilter( $db ) ); + + if ( !$authentication->run() ) + { + // return the status of the authentication, + // for example ezcAuthenticationDatabaseFilter::STATUS_PASSWORD_INCORRECT + $status = $authentication->getStatus(); + + // use the returned status to provide the user with a friendly error + // message, such as "The password you entered is incorect. Please try + // again.", and don't allow the user to see the protected content. + } + else + { + // allow the user to see the protected content + } + + + +.. + Local Variables: + mode: rst + fill-column: 79 + End: + vim: et syn=rst tw=79 nocin Property changes on: experimental/AuthenticationDatabaseTiein/design/design.txt ___________________________________________________________________ Name: svn:eol-style + native Added: experimental/AuthenticationDatabaseTiein/design/requirements.txt =================================================================== --- experimental/AuthenticationDatabaseTiein/design/requirements.txt 2007-05-04 14:55:21 UTC (rev 5059) +++ experimental/AuthenticationDatabaseTiein/design/requirements.txt 2007-05-04 14:58:45 UTC (rev 5060) @@ -0,0 +1,261 @@ +eZ Components - Authentication, Requirements +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +:Author: Alexandru Stanoi +:Revision: $Revision: $ +:Date: $Date: $ + + +Introduction +============ + +The purpose of the Authentication component is to provide support for different +means of identification and authentication of users using different providers and +protocols. + + +About authentication +==================== + +What is authentication? +----------------------- + +Authentication is a process of verifying the identity of an user and enabling +access for that user based on stored permissions. + +The steps of the authentication process are: + +Identification + Fetch the user credentials (eg. username + password, IP address, tokens). + +Authentication + Check user credentials with a security provider (eg. LDAP, database, htpasswd + file). + +Validation + Check if user is valid for the current context (eg. time of day). + +Authorization + Check if user has permissions for the current context (eg. printer access). + +The new Authentication component will implement only the Indentificaton and +Authentication stages. Validation and Authorization will be implemented at a +later point in time. + + +Authentication examples +----------------------- + +Login + The user enter their username (sometimes email address) and password. + Websites usually have a "Keep me logged-in" or "Remember me" checkbox to + avoid entering credentials everytime the user starts the application. The + application will compare the user's credentials against a database or another + provider, and allow the user access to the application. If user credentials + are not recognized, the application will deny access to the user. Sometimes + websites use other credentials in addition, like banks requiring users to use + a code generator (calculator) in response to the code generated by the + application. + +CAPTCHA + Not a proper authentication, it is just a way to secure certain features of + an application against scripts. The server generates a code and displays it + to the user in a scrambled image, and the user must enter the code in the + image to gain access to the secured feature (post comment, send email, etc). + +Confirmation ticket + Similar to CAPTCHA. The server generates a code and keeps it in a database + (or another storage), and sends an email to the user with the code. The user + uses this code in the application (usually by clicking a link in the email). + This is usually done to confirm the user's email address. The code is usually + deleted from the database after being used. + + +Requirements +============ + +The Authentication component should support adding filters (plug-ins) to the +authentication process. These filters will be processed in order, and only if +the previous filters allow the process to continue. If one filter fails (for +example if the password is incorrect), then the whole authentication process +stops and the status of the authentication can be used by the application +(for example to display "Password incorrect"). + + +Authentication filters +---------------------- + +A list of filters which are to be supported in the initial release of the +component (this list might be changed later): + +Session + Uses the PHP session to make information about the authenticated user + persistent across requests. This information includes if the user is + authenticated and authentication timestamp (to be used to expire the + session). + +Group + A generic filter which is used to group two or more filters, where only one + filter needs to succeed in order to continue the authentication. Example: + grouping the LDAP and Database filters; only one of the filters needs to + succeed for the group to succeed. + +Htpasswd file + Uses a Unix htpasswd file to authenticate users. Basic filter and not too + secure as the htpasswd file can be accessible to someone who has access to + the server. Should not be employed on critical application. It is used mostly + as an example. + +Database + Uses an existing database to authenticate user credentials. Should use + database abstraction to be able to authenticate against different database + providers (MySql, Oracle, etc) - this can be achieved with the Database and + DatabaseSchema components. + +Token + Support for authenticating against a user generated code. The code is stored + in a database (or other storage), and is deleted after the user has + authenticated against it. It is usually used for confirmation of the user's + email address. + +OpendID + Uses the OpenID protocol to authenticate users. The central idea of this + distributed protocol is that users login only once using their own URL. + (blog, personal website). Info: http://openid.net + +TypeKey + In many ways similar with OpenID, in that users login only once. Info: + http://www.sixapart.com/typekey + +LDAP (Lightweight Directory Access Protocol) + Protocol for querying and updating directory services. Compatible with + other protocols (Novell eDirectory, Oracle Internet Directory, Windows Server + 2003 Active Directory). RFC: http://www.faqs.org/rfcs/rfc4510.html + + +Design goals +============ + +The authentication process is divided into filters (plug-ins). The developer +can decide which filters the application should employ and their order. + +The list of filters can be extended by developers, and creating new filters +should not affect existing code. + +The session is optional and is used to make the authentication persistent +across requests. If the session is enabled, the authentication process starts +at the session, where it will check if the user is already authenticated. If +the session expired or if the user is not authenticated, the other filters in +the authentication process will be run. If the authentication process was +successful, then the session will save the authentication information to be +used in subsequent requests. + +The logging of authorization attempts will not be done by the Authentication +component, but by the application (eventually using the EventLog component). + + +Authentication process +---------------------- + +The filters run in sequence. Based on the return status of each filter, the +authentication process will continue or stop as follows: + +Continue + The next filter will be run. If all filters are run and positive answer + is received from all of them, then the user is granted access to the + application. + +Error + The authentication process will stop (or not, depending on the options), and + a status object will contain the error. The application will decide, based on + the error status, what to do (for example display an error message like + "Password incorrect"). + +Stop + The authentication process will stop regardless of what filters are still in + the queue, and the user is granted access to the application. + +Schematic: :: + START + | + V + NO (Error) ----------- + -------------------------| Session |------------------- + | ----------- | YES (Stop) + | | YES (Continue) | + | V | + V NO (Error) ------------ V + ------------------------| Database |----------------- + | ------------ | YES (Stop) + | | YES (Continue) | + | V | + V NO (Error) ------------ V + ------------------------| LDAP |----------------- + | ------------ | YES (Stop) + | | YES (Continue) | + V V V + =================== ====================================== + ( not authenticated ) ( authenticated ) + =================== ====================================== + +This behaviour can be changed with an option for each filter, which specifies +if the filter stops the authentication process if it is successful, or allows +the authentication process to continue. + + +Session +------- + +The use of a Session filter is optional (but enabled by default). Developers can +specify the provided Session filter or their own class. + +If the Session filter is enabled, then it will be checked before the +authentication process, and it will save the authentication information for +future requests, after the process. + +The Session filter is responsible for: + - saving and checking the timestamp (based on options) + - starting and ending the PHP session + - regenerating the session ID + + +Grouping of filters +------------------- + +The developer of the application can group similar filters together, where only +one filter needs to succeed for the filter group to succeed. + +For example: the user credentials can be checked against the local database or +an LDAP provider, but it needs not be present in both providers. In this case +the LDAP and Database filters will be grouped together, and if at least one +filter succeed, then the group filter will succeed. + + +PHP requirements +================ + +Extensions needed for the authentication: + - TypeKey: bcmath or gmp + - OpenID: openssl + - LDAP: ldap; oci8 (plus Oracle enviroment) is required for OracleLDAP + - parsing of XML documents: simplexml (usually enabled by default) + + +Security considerations +======================= + +Due to the nature of this component, care must be taken to ensure secure +handling of resources. + +Session attacks will be prevented with these methods: + - prevent session fixation (http://en.wikipedia.org/wiki/Session_fixation) + - regenerate session id if not authenticated + + + + +.. + Local Variables: + mode: rst + fill-column: 79 + End: + vim: et syn=rst tw=79 nocin Property changes on: experimental/AuthenticationDatabaseTiein/design/requirements.txt ___________________________________________________________________ Name: svn:eol-style + native Added: experimental/AuthenticationDatabaseTiein/docs/tutorial/tutorial_database.php =================================================================== --- experimental/AuthenticationDatabaseTiein/docs/tutorial/tutorial_database.php 2007-05-04 14:55:21 UTC (rev 5059) +++ experimental/AuthenticationDatabaseTiein/docs/tutorial/tutorial_database.php 2007-05-04 14:58:45 UTC (rev 5060) @@ -0,0 +1,37 @@ +<?php +$credentials = new ezcAuthenticationPasswordCredentials( 'jan.modaal', 'b1b3773a05c0ed0176787a4f1574ff0075f7521e' ); +$database = new ezcAuthenticationDatabaseInfo( ezcDbInstance::get(), 'users', array( 'user', 'password' ) ); +$authentication = new ezcAuthentication( $credentials ); +$authentication->addFilter( new ezcAuthenticationDatabaseFilter( $database ) ); +if ( !$authentication->run() ) +{ + // authentication did not succeed, so inform the user + $status = $authentication->getStatus(); + $err = array(); + $err["user"] = ""; + $err["password"] = ""; + for ( $i = 0; $i < count( $status ); $i++ ) + { + list( $key, $value ) = each( $status[$i] ); + switch ( $key ) + { + case 'ezcAuthenticationDatabaseFilter': + if ( $value === ezcAuthenticationDatabaseFilter::STATUS_USERNAME_INCORRECT ) + { + $err["user"] = "<span class='error'>Username incorrect</span>"; + } + if ( $value === ezcAuthenticationDatabaseFilter::STATUS_PASSWORD_INCORRECT ) + { + $err["password"] = "<span class='error'>Password incorrect</span>"; + } + break; + } + } + // use $err array (with a Template object for example) to display the login form + // to the user with "Password incorrect" message next to the password field, etc... +} +else +{ + // authentication succeeded, so allow the user to see his content +} +?> Property changes on: experimental/AuthenticationDatabaseTiein/docs/tutorial/tutorial_database.php ___________________________________________________________________ Name: svn:eol-style + native Added: experimental/AuthenticationDatabaseTiein/docs/tutorial.txt =================================================================== --- experimental/AuthenticationDatabaseTiein/docs/tutorial.txt 2007-05-04 14:55:21 UTC (rev 5059) +++ experimental/AuthenticationDatabaseTiein/docs/tutorial.txt 2007-05-04 14:58:45 UTC (rev 5060) @@ -0,0 +1,63 @@ +eZ Components - Authentication +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. contents:: Table of Contents + +Introduction +============ + +Description +----------- + +The purpose of the Authentication component is to provide support for different +means of identification and authentication of users using different providers and +protocols. + + +Class overview +============== + +An overview of the most important classes in the Authentication component. + + +Base classes +------------ + +ezcAuthentication + Main class of Authentication. It is a container for authentication filters, + which will be run in sequence. The method run() returns true or false + depending on the success of the authentication filters. + +ezcAuthenticationCredentials + Structure which holds user credentials. Types are id credentials + (ezcAuthenticationIdCredentials) and id + password credentials + (ezcAuthenticationPasswordCredentials). + + +Authentication filters +---------------------- + +ezcAuthenticationDatabaseFilter + Filter to authenticate against a database. Uses a database instance provided + by the Database component (via the ezcDbInstance::get() function). + + +Authentication filters +====================== + +Database +-------- + +The following example shows how to authenticate against a database. + +.. include:: tutorial/tutorial_database.php + :literal: + + + +.. + Local Variables: + mode: rst + fill-column: 79 + End: + vim: et syn=rst tw=79 nocin Property changes on: experimental/AuthenticationDatabaseTiein/docs/tutorial.txt ___________________________________________________________________ Name: svn:eol-style + native Added: experimental/AuthenticationDatabaseTiein/src/authentication_database_autoload.php =================================================================== --- experimental/AuthenticationDatabaseTiein/src/authentication_database_autoload.php 2007-05-04 14:55:21 UTC (rev 5059) +++ experimental/AuthenticationDatabaseTiein/src/authentication_database_autoload.php 2007-05-04 14:58:45 UTC (rev 5060) @@ -0,0 +1,20 @@ +<?php +/** + * Autoloader definition for the ezcAuthenticationDatabaseTiein component. + * + * @copyright Copyright (C) 2005-2007 eZ systems as. All rights reserved. + * @license http://ez.no/licenses/new_bsd New BSD License + * @filesource + * @package AuthenticationDatabaseTiein + * @version //autogen// + */ + +return array( + + // authentication Database filter + 'ezcAuthenticationDatabaseFilter' => 'AuthenticationDatabaseTiein/filters/database/database_filter.php', + 'ezcAuthenticationDatabaseInfo' => 'AuthenticationDatabaseTiein/filters/database/database_info.php', + 'ezcAuthenticationDatabaseOptions' => 'AuthenticationDatabaseTiein/filters/database/database_options.php', + + ); +?> Property changes on: experimental/AuthenticationDatabaseTiein/src/authentication_database_autoload.php ___________________________________________________________________ Name: svn:eol-style + native Added: experimental/AuthenticationDatabaseTiein/src/filters/database/database_filter.php =================================================================== --- experimental/AuthenticationDatabaseTiein/src/filters/database/database_filter.php 2007-05-04 14:55:21 UTC (rev 5059) +++ experimental/AuthenticationDatabaseTiein/src/filters/database/database_filter.php 2007-05-04 14:58:45 UTC (rev 5060) @@ -0,0 +1,211 @@ +<?php +/** + * File containing the ezcAuthenticationDatabaseFilter class. + * + * @copyright Copyright (C) 2005-2007 eZ systems as. All rights reserved. + * @license http://ez.no/licenses/new_bsd New BSD License + * @filesource + * @package AuthenticationDatabaseTiein + * @version //autogen// + */ + +/** + * Filter to authenticate against a database. + * + * The database instance to use is specified using a ezcAuthenticationDatabaseInfo + * structure. Table name and field names are specified in the same structure. + * + * Example: + * <code> + * $credentials = new ezcAuthenticationPasswordCredentials( 'jan.modaal', 'b1b3773a05c0ed0176787a4f1574ff0075f7521e' ); + * $database = new ezcAuthenticationDatabaseInfo( ezcDbInstance::get(), 'users', array( 'user', 'password' ) ); + * $authentication = new ezcAuthentication( $credentials ); + * $authentication->addFilter( new ezcAuthenticationDatabaseFilter( $database ) ); + * if ( !$authentication->run() ) + * { + * // authentication did not succeed, so inform the user + * $status = $authentication->getStatus(); + * $err = array(); + * $err["user"] = ""; + * $err["password"] = ""; + * for ( $i = 0; $i < count( $status ); $i++ ) + * { + * list( $key, $value ) = each( $status[$i] ); + * switch ( $key ) + * { + * case 'ezcAuthenticationDatabaseFilter': + * if ( $value === ezcAuthenticationDatabaseFilter::STATUS_USERNAME_INCORRECT ) + * { + * $err["user"] = "<span class='error'>Username incorrect</span>"; + * } + * if ( $value === ezcAuthenticationDatabaseFilter::STATUS_PASSWORD_INCORRECT ) + * { + * $err["password"] = "<span class='error'>Password incorrect</span>"; + * } + * break; + * } + * } + * // use $err array (with a Template object for example) to display the login form + * // to the user with "Password incorrect" message next to the password field, etc... + * } + * else + * { + * // authentication succeeded, so allow the user to see his content + * } + * </code> + * + * @property ezcAuthenticationDatabaseInfo $database + * Structure which holds a database instance, table name and fields + * which are used for authentication. + * + * @package AuthenticationDatabaseTiein + * @version //autogen// + * @mainclass + */ +class ezcAuthenticationDatabaseFilter extends ezcAuthenticationFilter +{ + /** + * Username is not found in the database. + */ + const STATUS_USERNAME_INCORRECT = 1; + + /** + * Password is incorrect. + */ + const STATUS_PASSWORD_INCORRECT = 2; + + /** + * Holds the properties of this class. + * + * @var array(string=>mixed) + */ + private $properties = array(); + + /** + * Creates a new object of this class. + * + * @param ezcAuthenticationDatabaseInfo $database Database to use in authentication + * @param ezcAuthenticationDatabaseOptions $options Options for this class + */ + public function __construct( ezcAuthenticationDatabaseInfo $database, ezcAuthenticationDatabaseOptions $options = null ) + { + $this->options = ( $options === null ) ? new ezcAuthenticationDatabaseOptions() : $options; + $this->database = $database; + } + + /** + * Sets the property $name to $value. + * + * @throws ezcBasePropertyNotFoundException + * if the property $name does not exist + * @throws ezcBaseValueException + * if $value is not correct for the property $name + * @param string $name + * @param mixed $value + * @ignore + */ + public function __set( $name, $value ) + { + switch ( $name ) + { + case 'database': + if ( $value instanceof ezcAuthenticationDatabaseInfo ) + { + $this->properties[$name] = $value; + } + else + { + throw new ezcBaseValueException( $name, $value, 'instance of ezcAuthenticationDatabaseInfo' ); + } + break; + + default: + throw new ezcBasePropertyNotFoundException( $name ); + } + } + + /** + * Returns the value of the property $name. + * + * @throws ezcBasePropertyNotFoundException + * if the property $name does not exist + * @param string $name + * @return mixed + * @ignore + */ + public function __get( $name ) + { + switch ( $name ) + { + case 'database': + return $this->properties[$name]; + + default: + throw new ezcBasePropertyNotFoundException( $name ); + } + } + + /** + * Returns true if the property $name is set, otherwise false. + * + * @param string $name + * @return bool + * @ignore + */ + public function __isset( $name ) + { + switch ( $name ) + { + case 'database': + return isset( $this->properties[$name] ); + + default: + return false; + } + } + + /** + * Runs the filter and returns a status code when finished. + * + * @param ezcAuthenticationPasswordCredentials $credentials Authentication credentials + * @return int + */ + public function run( $credentials ) + { + // see if username exists + $query = new ezcQuerySelect( $this->database->instance ); + $e = $query->expr; + $query->select( 'COUNT(*)' ) + ->from( $this->database->table ) + ->where( + $e->eq( $this->database->fields[0], $query->bindValue( $credentials->id ) ) + ); + $rows = $query->prepare(); + $rows->execute(); + $count = (int)$rows->fetchColumn( 0 ); + if ( $count === 0 ) + { + return self::STATUS_USERNAME_INCORRECT; + } + + // see if username has the specified password + $query = new ezcQuerySelect( $this->database->instance ); + $e = $query->expr; + $query->select( 'COUNT(*)' ) + ->from( $this->database->table ) + ->where( $e->lAnd( + $e->eq( $this->database->fields[0], $query->bindValue( $credentials->id ) ), + $e->eq( $this->database->fields[1], $query->bindValue( $credentials->password ) ) + ) ); + $rows = $query->prepare(); + $rows->execute(); + $count = (int)$rows->fetchColumn( 0 ); + if ( $count === 0 ) + { + return self::STATUS_PASSWORD_INCORRECT; + } + + return self::STATUS_OK; + } +} +?> Property changes on: experimental/AuthenticationDatabaseTiein/src/filters/database/database_filter.php ___________________________________________________________________ Name: svn:eol-style + native Added: experimental/AuthenticationDatabaseTiein/src/filters/database/database_info.php =================================================================== --- experimental/AuthenticationDatabaseTiein/src/filters/database/database_info.php 2007-05-04 14:55:21 UTC (rev 5059) +++ experimental/AuthenticationDatabaseTiein/src/filters/database/database_info.php 2007-05-04 14:58:45 UTC (rev 5060) @@ -0,0 +1,73 @@ +<?php +/** + * File containing the ezcAuthenticationDatabaseInfo structure. + * + * @copyright Copyright (C) 2005-2007 eZ systems as. All rights reserved. + * @license http://ez.no/licenses/new_bsd New BSD License + * @filesource + * @package AuthenticationDatabaseTiein + * @version //autogen// + */ + +/** + * Structure for defining the database and table to authenticate against. + * + * @package AuthenticationDatabaseTiein + * @version //autogen// + */ +class ezcAuthenticationDatabaseInfo extends ezcBaseStruct +{ + /** + * Database instance. + * + * @var ezcDbHandler + */ + public $instance; + + /** + * Table which stores the user credentials. + * + * @var string + */ + public $table; + + /** + * Fields which hold the user credentials. + * + * @var array(string) + */ + public $fields; + + /** + * Constructs a new ezcAuthenticationDatabaseInfo object. + * + * @param ezcDbHandler $instance Database instance to use + * @param string $table Table which stores usernames and passwords + * @param array(string) $fields The fields which hold usernames and passwords + */ + public function __construct( ezcDbHandler $instance, $table, array $fields ) + { + $this->instance = $instance; + $this->table = $table; + $this->fields = $fields; + } + + /** + * Returns a new instance of this class with the data specified by $array. + * + * $array contains all the data members of this class in the form: + * array('member_name'=>value). + * + * __set_state makes this class exportable with var_export. + * var_export() generates code, that calls this method when it + * is parsed with PHP. + * + * @param array(string=>mixed) + * @return ezcAuthenticationDatabaseInfo + */ + static public function __set_state( array $array ) + { + return new ezcAuthenticationDatabaseInfo( $array['instance'], $array['table'], $array['fields'] ); + } +} +?> Property changes on: experimental/AuthenticationDatabaseTiein/src/filters/database/database_info.php ___________________________________________________________________ Name: svn:eol-style + native Added: experimental/AuthenticationDatabaseTiein/src/filters/database/database_options.php =================================================================== --- experimental/AuthenticationDatabaseTiein/src/filters/database/database_options.php 2007-05-04 14:55:21 UTC (rev 5059) +++ experimental/AuthenticationDatabaseTiein/src/filters/database/database_options.php 2007-05-04 14:58:45 UTC (rev 5060) @@ -0,0 +1,54 @@ +<?php +/** + * File containing the ezcAuthenticationDatabaseOptions class. + * + * @copyright Copyright (C) 2005-2007 eZ systems as. All rights reserved. + * @license http://ez.no/licenses/new_bsd New BSD License + * @filesource + * @package AuthenticationDatabaseTiein + * @version //autogen// + */ + +/** + * Class containing the options for the database authentication filter. + * + * @package AuthenticationDatabaseTiein + * @version //autogen// + */ +class ezcAuthenticationDatabaseOptions extends ezcAuthenticationFilterOptions +{ + /** + * Constructs an object with the specified values. + * + * @throws ezcBasePropertyNotFoundException + * if $options contains a property not defined + * @throws ezcBaseValueException + * if $options contains a property with a value not allowed + * @param array(string=>mixed) $options + */ + public function __construct( array $options = array() ) + { + parent::__construct( $options ); + } + + /** + * Sets the option $name to $value. + * + * @throws ezcBasePropertyNotFoundException + * if the property $name is not defined + * @throws ezcBaseValueException + * if $value is not correct for the property $name + * @param string $name + * @param mixed $value + * @ignore + */ + public function __set( $name, $value ) + { + switch ( $name ) + { + default: + parent::__set( $name, $value ); + } + } +} +?> Property changes on: experimental/AuthenticationDatabaseTiein/src/filters/database/database_options.php ___________________________________________________________________ Name: svn:eol-style + native Added: experimental/AuthenticationDatabaseTiein/tests/filters/database/database_test.php =================================================================== --- experimental/AuthenticationDatabaseTiein/tests/filters/database/database_test.php 2007-05-04 14:55:21 UTC (rev 5059) +++ experimental/AuthenticationDatabaseTiein/tests/filters/database/database_test.php 2007-05-04 14:58:45 UTC (rev 5060) @@ -0,0 +1,231 @@ +<?php +/** + * @copyright Copyright (C) 2005-2007 eZ systems as. All rights reserved. + * @license http://ez.no/licenses/new_bsd New BSD License + * @filesource + * @package AuthenticationDatabaseTiein + * @version //autogen// + * @subpackage Tests + */ + +/** + * @package AuthenticationDatabaseTiein + * @version //autogen// + * @subpackage Tests + */ +class ezcAuthenticationDatabaseTest extends ezcTestCase +{ + public static function suite() + { + return new PHPUnit_Framework_TestSuite( "ezcAuthenticationDatabaseTest" ); + } + + public function setUp() + { + try + { + $this->db = ezcDbInstance::get(); + $tables = array( 'users' => new ezcDbSchemaTable( + array ( + 'id' => new ezcDbSchemaField( 'integer', false, true, null, true ), + 'user' => new ezcDbSchemaField( 'text', 32, true ), + 'password' => new ezcDbSchemaField( 'text', 64, true ), + ), + array ( + 'user' => new ezcDbSchemaIndex( array ( 'user' => new ezcDbSchemaIndexField() ), false, false ), + ) ) ); + $schema = new ezcDbSchema( $tables ); + $schema->writeToDb( $this->db ); + $query = new ezcQueryInsert( $this->db ); + $query->insertInto( 'users' ) + ->set( 'user', $query->bindValue( 'jan.modaal' ) ) + ->set( 'password', $query->bindValue( sha1( 'qwerty' ) ) ); + $stmt = $query->prepare(); + $stmt->execute(); + $query = new ezcQueryInsert( $this->db ); + $query->insertInto( 'users' ) + ->set( 'user', $query->bindValue( 'john.doe' ) ) + ->set( 'password', $query->bindValue( crypt( 'foobar', 'jo' ) ) ); + $stmt = $query->prepare(); + $stmt->execute(); + $query = new ezcQueryInsert( $this->db ); + $query->insertInto( 'users' ) + ->set( 'user', $query->bindValue( 'zhang.san' ) ) + ->set( 'password', $query->bindValue( md5( 'asdfgh' ) ) ); + $stmt = $query->prepare(); + $stmt->execute(); + $query = new ezcQueryInsert( $this->db ); + $query->insertInto( 'users' ) + ->set( 'user', $query->bindValue( 'hans.mustermann' ) ) + ->set( 'password', $query->bindValue( 'abcdef' ) ); + $stmt = $query->prepare(); + $stmt->execute(); + } + catch ( Exception $e ) + { + $this->markTestSkipped(); + } + } + + public function tearDown() + { + $this->db->exec( 'DROP TABLE users' ); + } + + public function testDatabasePasswordNull() + { + $credentials = new ezcAuthenticationPasswordCredentials( 'jan.modaal', null ); + $database = new ezcAuthenticationDatabaseInfo( $this->db, 'users', array( 'user', 'password' ) ); + $authentication = new ezcAuthentication( $credentials ); + $authentication->addFilter( new ezcAuthenticationDatabaseFilter( $database ) ); + $this->assertEquals( false, $authentication->run() ); + } + + public function testDatabaseSha1Correct() + { + $credentials = new ezcAuthenticationPasswordCredentials( 'jan.modaal', 'b1b3773a05c0ed0176787a4f1574ff0075f7521e' ); + $database = new ezcAuthenticationDatabaseInfo( $this->db, 'users', array( 'user', 'password' ) ); + $authentication = new ezcAuthentication( $credentials ); + $authentication->addFilter( new ezcAuthenticationDatabaseFilter( $database ) ); + $this->assertEquals( true, $authentication->run() ); + } + + public function testDatabaseSha1Fail() + { + $credentials = new ezcAuthenticationPasswordCredentials( 'jan.modaal', 'wrong password' ); + $database = new ezcAuthenticationDatabaseInfo( $this->db, 'users', array( 'user', 'password' ) ); + $authentication = new ezcAuthentication( $credentials ); + $authentication->addFilter( new ezcAuthenticationDatabaseFilter( $database ) ); + $this->assertEquals( false, $authentication->run() ); + } + + public function testDatabaseCryptCorrect() + { + $credentials = new ezcAuthenticationPasswordCredentials( 'john.doe', 'joB9EZ4O1cXDk' ); + $database = new ezcAuthenticationDatabaseInfo( $this->db, 'users', array( 'user', 'password' ) ); + $authentication = new ezcAuthentication( $credentials ); + $authentication->addFilter( new ezcAuthenticationDatabaseFilter( $database ) ); + $this->assertEquals( true, $authentication->run() ); + } + + public function testDatabaseCryptFail() + { + $credentials = new ezcAuthenticationPasswordCredentials( 'john.doe', 'wrong password' ); + $database = new ezcAuthenticationDatabaseInfo( $this->db, 'users', array( 'user', 'password' ) ); + $authentication = new ezcAuthentication( $credentials ); + $authentication->addFilter( new ezcAuthenticationDatabaseFilter( $database ) ); + $this->assertEquals( false, $authentication->run() ); + } + + public function testDatabaseMd5Correct() + { + $credentials = new ezcAuthenticationPasswordCredentials( 'zhang.san', 'a152e841783914146e4bcd4f39100686' ); + $database = new ezcAuthenticationDatabaseInfo( $this->db, 'users', array( 'user', 'password' ) ); + $authentication = new ezcAuthentication( $credentials ); + $authentication->addFilter( new ezcAuthenticationDatabaseFilter( $database ) ); + $this->assertEquals( true, $authentication->run() ); + } + + public function testDatabaseMd5Fail() + { + $credentials = new ezcAuthenticationPasswordCredentials( 'zhang.san', 'wrong password' ); + $database = new ezcAuthenticationDatabaseInfo( $this->db, 'users', array( 'user', 'password' ) ); + $authentication = new ezcAuthentication( $credentials ); + $authentication->addFilter( new ezcAuthenticationDatabaseFilter( $database ) ); + $this->assertEquals( false, $authentication->run() ); + } + + public function testDatabasePlainCorrect() + { + $credentials = new ezcAuthenticationPasswordCredentials( 'hans.mustermann', 'abcdef' ); + $database = new ezcAuthenticationDatabaseInfo( $this->db, 'users', array( 'user', 'password' ) ); + $authentication = new ezcAuthentication( $credentials ); + $authentication->addFilter( new ezcAuthenticationDatabaseFilter( $database ) ); + $this->assertEquals( true, $authentication->run() ); + } + + public function testDatabasePlainFail() + { + $credentials = new ezcAuthenticationPasswordCredentials( 'hans.mustermann', 'wrong password' ); + $database = new ezcAuthenticationDatabaseInfo( $this->db, 'users', array( 'user', 'password' ) ); + $authentication = new ezcAuthentication( $credentials ); + $authentication->addFilter( new ezcAuthenticationDatabaseFilter( $database ) ); + $this->assertEquals( false, $authentication->run() ); + } + + public function testDatabasePlainFailIncorrectUsername() + { + $credentials = new ezcAuthenticationPasswordCredentials( 'no such user', 'wrong password' ); + $database = new ezcAuthenticationDatabaseInfo( $this->db, 'users', array( 'user', 'password' ) ); + $authentication = new ezcAuthentication( $credentials ); + $authentication->addFilter( new ezcAuthenticationDatabaseFilter( $database ) ); + $this->assertEquals( false, $authentication->run() ); + } + + public function testDatabaseInfo() + { + $database = ezcAuthenticationDatabaseInfo::__set_state( array( 'instance' => $this->db, 'table' => 'users', 'fields' => array( 'user', 'password' ) ) ); + $this->assertEquals( $this->db, $database->instance ); + $this->assertEquals( 'users', $database->table ); + $this->assertEquals( array( 'user', 'password' ), $database->fields ); + } + + public function testDatabaseOptions() + { + $options = new ezcAuthenticationDatabaseOptions(); + + try + { + $options->no_such_option = 'wrong value'; + $this->fail( "Expected exception was not thrown." ); + } + catch ( ezcBasePropertyNotFoundException $e ) + { + $this->assertEquals( "No such property name 'no_such_option'.", $e->getMessage() ); + } + + $database = new ezcAuthenticationDatabaseInfo( $this->db, 'users', array( 'user', 'password' ) ); + $filter = new ezcAuthenticationDatabaseFilter( $database ); + $filter->setOptions( $options ); + $this->assertEquals( $options, $filter->getOptions() ); + } + + public function testDatabaseProperties() + { + $database = new ezcAuthenticationDatabaseInfo( $this->db, 'users', array( 'user', 'password' ) ); + $filter = new ezcAuthenticationDatabaseFilter( $database ); + $this->assertEquals( true, isset( $filter->database ) ); + $this->assertEquals( false, isset( $filter->no_such_property ) ); + + try + { + $filter->no_such_property = 'wrong value'; + $this->fail( "Expected exception was not thrown." ); + } + catch ( ezcBasePropertyNotFoundException $e ) + { + $this->assertEquals( "No such property name 'no_such_property'.", $e->getMessage() ); + } + + try + { + $filter->database = 'wrong value'; + $this->fail( "Expected exception was not thrown." ); + } + catch ( ezcBaseValueException $e ) + { + $this->assertEquals( "The value 'wrong value' that you were trying to assign to setting 'database' is invalid. Allowed values are: instance of ezcAuthenticationDatabaseInfo.", $e->getMessage() ); + } + + try + { + $value = $filter->no_such_property; + $this->fail( "Expected exception was not thrown." ); + } + catch ( ezcBasePropertyNotFoundException $e ) + { + $this->assertEquals( "No such property name 'no_such_property'.", $e->getMessage() ); + } + } +} +?> Property changes on: experimental/AuthenticationDatabaseTiein/tests/filters/database/database_test.php ___________________________________________________________________ Name: svn:eol-style + native Added: experimental/AuthenticationDatabaseTiein/tests/suite.php =================================================================== --- experimental/AuthenticationDatabaseTiein/tests/suite.php 2007-05-04 14:55:21 UTC (rev 5059) +++ experimental/AuthenticationDatabaseTiein/tests/suite.php 2007-05-04 14:58:45 UTC (rev 5060) @@ -0,0 +1,39 @@ +<?php +/** + * File containing the ezcAuthenticationDatabaseTieinSuite class. + * + * @copyright Copyright (C) 2005-2007 eZ systems as. All rights reserved. + * @license http://ez.no/licenses/new_bsd New BSD License + * @filesource + * @package AuthenticationDatabaseTiein + * @version //autogen// + * @subpackage Tests + */ + +/** + * Including the tests + */ +require_once( "filters/database/database_test.php" ); + +/** + * @package AuthenticationDatabaseTiein + * @version //autogen// + * @subpackage Tests + */ +class ezcAuthenticationDatabaseTieinSuite extends PHPUnit_Framework_TestSuite +{ + public function __construct() + { + parent::__construct(); + $this->setName( "AuthenticationDatabaseTiein" ); + ezcBase::addClassRepository( '/home/as/dev/ezcomponents/experimental', '/home/as/dev/ezcomponents/experimental/autoload' ); + + $this->addTest( ezcAuthenticationDatabaseTest::suite() ); + } + + public static function suite() + { + return new ezcAuthenticationDatabaseTieinSuite(); + } +} +?> Property changes on: experimental/AuthenticationDatabaseTiein/tests/suite.php ___________________________________________________________________ Name: svn:eol-style + native -- svn-components mailing list svn-components@lists.ez.no http://lists.ez.no/mailman/listinfo/svn-components