PHP Login: Access_user Class

Access_user Class is an easy to use system for protecting pages and register users. They main features are: User-login, user registration, user update, remember login information, page protection, forgotten password recovery, mail based account activation and multi language message reporting and since the latest versions: maintain extra user profile information, access levels, a limited (safe) admin panel, manual account activation and an improved password check. The class is powered by MySQL and PHP sessions. Inside the package are examples for all primary methods. Since version 1.92 custom session handler are supported.

PHP Script Download

Documentation

This class requires a PHP enabled Apache (virtual) host. I tested this class with PHP 4.3(5.1) and MySQL 3.23(4.1) on Windows and Linux. I never tested this class with IIS. If you want to use this class on Windows / IIS than you have to be sure that the server variable DOCUMENT_ROOT is available. You can test this while using this code on your web host:

echo getenv("DOCUMENT_ROOT");

If you can’t see the document path, then this class will not work out of the box. I’m sure it is possible to change all paths but there is no information about on this page or inside the files.

For windows user using this class on a localhost:

You need a mail server program to run some of the scripts (register.php, forgot_password.php and update_user.php)

Database selection

By default the database is not selected with the PHP function mysql_select_db() and the database name is in front of the table name. It’s possible that your server doesn’t allow the database name inside a query, if this forms a problem then don’t use them there and un-escape the mysql_select_db() function inside the connect_db() method.

Installation

  • Use the “users_table.sql” file to create your MySQL table.
  • Since version 1.92 it’s possible to safe the session data inside your MySQL database (is more safe on shared hosting)
  • Create a file called db.php (I place it into the folder classes which is one above the root), add this code with your database connection parameters:
    <?php
    define("DB_SERVER", "localhost");
    define("DB_NAME", "database");
    define ("DB_USER", "user");
    define ("DB_PASSWORD", "password");
  • Most important, change all important paths…
    • APPLICATION_PATH: the directory where your scripts are placed
    • CLASS_PATH: this path is dynamic, use it if all files are inside the same directory
    • … or use your own ones (only needed for LOGIN_PAGE, START_PAGE and ACTIVE_PASS_PAGE)
  • To fit the existing path structure in all example files you have to create two folders:
    • the first “classes” is above your document root…
    • …the second “access_user” is inside the classes folder.
  • Place the class- and config file inside “access_user” folder.
  • After this you can use all example files (except the three files defined inside the config file) on different locations from your site.

How does it work?

  • Run the register.php in your web browser and enter the first user into your database.
  • After successful registration you will get an confirmation mail,
    • activate and confirm your account and you can enter the protected pages
    • use the manual activation status and the site admin have to activate each single account.
  • Login and you have assess to the update page where it’s possible to modify the user information.
  • If you change the e-mail address you get a new confirmation e-mail, activate the new address with the given link.
  • Click on log out or exit you browser to end the session.
  • If you have forgotten the password and or login, you can use the e-mail address to get a reminder message.

How to use?

Remember, all example files are full working. The next documentation is only to explain what the methods / variables exactly do.

A note about the usage of the “automatic login” feature: If a cookie is saved on the client side, the user doesn’t need to login (new in version 1.94)

login.php

Find in this file a form with to text fields one for the login and one for the password. These entries will be validated before you can enter the protected area.
I use this page as the target for the account activation process, too.
Important: If you use the feature “Visitor count”, the table field extra_info can’t be used for other information!

Note: Since version 1.92 if the login cookie function is used, the recovered (encrypted) password inside the password form field is always 32 chars long. This is not a problem, the script can handle that.

Important methods and variables on this page:

$my_access->save_login // use a cookie to remember the client login, possible values are "yes" or "no"
$my_access->count_visit = true // if this is true then the last visit date is saved in the database (field extra_info)
$my_access->login_user($user, $password) // call the login method
$my_access->activate_account($activate_key, $key_id) // the account activation method
$my_access->validate_email($validation_key, $key_id) // (updated) e-mail address validation

This class can be used in two modes:

  • automatic account activation
  • account activation by admin (check the default account details beneath)

If you want to disable the automatic activation feature, use this variable inside the login script: $my_access->auto_activation = false; // (true/false) or set this boolean inside the class file.

logout.php

If you use the setting USE_MYSQL_SESSIONS inside the config file you need a logout page without class object to clear the old session data from the database.

register.php

The register.php file is a regular form with fields for login, password, e-mail, real name and for extra information. My suggestion is, removing the last field and using instead the extra info field for information like: language, register date, customer number etc. To register a new user only one method required:

$new_member->register_user($first_login, $first_password, $confirm_password, $first_name, $first_info, $first_email)

Of course there are also standard variables for error messages and to switch messages in different languages (like in the other examples).

update_user.php

Use this example where the user can update his information like: e-mail, password, extra info and his real name. The login name is unique and can’t be changed. If the user changed his e-mail address a confirmation mail is send to his new address and the old one is active until he confirmed the new one. The user can change his password if he let the password field empty, the password will not be changed. Methods for this example are:

$update_member->access_page() // protect this page too.
$update_member->get_user_info() // call this method to get all the user information
$update_member->update_user($new_password, $new_confirm, $new_name, $new_info, $new_mail) // the update method

forgot_password.php

If a user forgot his password and/or login he can request a reminder mail. Using this file the user fills the form field with the e-mail address which is used during registration. After submitting the user get a mail with a link to the (next) file where you can (re)enter a new password. Only one method is required (the error message functions as a important option):

$renew_password->forgot_password($forgot_email) // call the method with the entered mail address as property

activate_password.php

If the user use the link inside the mail he got, he will reach this page. On this page the user have the option to enter a new password for his account. After submitting this new password the user can use it in the login form.

$act_password->check_activation_password($controle_str, $id) // this will check the query string for valid data
$act_password->activate_new_password($new_pass, $new_confirm, $old_pass) // this update the record with the new password

I put the activation string into a session in place of a hidden field.

example.php

Use the code from this file in all pages you want to protect. I use this file to link to protected pages like “update_user.php”. Notice these methods and variables:

$page_protect->access_page() // only set this this method to protect your page!
$page_protect->log_out() // the method to log off (optional)

testpage.php

I created this optional page to show how this class take care of previous pages if the user have to login first.

$test_page_protect->access_page($_SERVER['PHP_SELF'], $_SERVER['QUERY_STRING']) // set this method, including the server vars to protect your page and get redirected to here after login

Use this method the same like before, except that you enter these two server variables.

test_access_level.php

This file is an example to test the access level from a user. Find the link on the example.php page.

$test_access_level->access_page($_SERVER['PHP_SELF'], "", 5) // the last parameter is the value of the access level. Configure the levels inside the db_config.php file.

admin_user.php

This file is also an extension, with this file it’s possible to change user data like the password (reset), email address, activation status and access level.

Use the example record to admin users (after installation): user: administrator / password: welcome

$admin_update->get_userdata($for_user, $type = "login"); // obtain the user data to show in the admin form ($type is used to select dat by "id" or "login"
$admin_update->update_user_by_admin($new_level, $user_id, $def_pass, $new_email, $active, $confirmation = "no"); // with this method only a few data can be updated by the administrator. The last parameter is used to send a conformation mail
$admin_update->access_level_menu($curr_level, $element_name = "level") // a simple select menu will show the min - max value of the access levels

Change log for the PHP Login: Access_user Class

Version 1.99

In the past there was only support for PHP’s mail() function to send mail messages. Since some users can’t use the mail function because the hosting company doesn’t allow this, we decided to implement the PHPmailer class as a second option. Now it’s possible to send the messages via the mail() function, the sendmail mail program provided by Linux or via SMTP. The two last options are possible with PHPmailer class. ThePHPmailer class is not included. Check the updated send_mail() method and the new constant variables inside the configuration file.

Version 1.98

This is an important (security related) update, in previous versions hackers can guess common and repeating passwords from user. While the “forgotten password” function was based on the password and the user id, it could be possible to change the password for some user (if the hacker knows the users id and the right password). The risk is not very high for most installations but could be work out some trouble. The new version doesn’t use the password for validation anymore. The login name (encrypted) is used together with some “secret” secret string. AU class user can replace the class file but need to update the method calls in the activate password script. You need to add the constant variable SECRET_STRING to the config file.

Version 1.97

There was a small bug inside the constructor method of the user_profile extension, this is fixed now. In previous versions with auto-activation enabled it was possible to activate an account via the activation email after the admin has de-activated an account. The method activate_account() is changed to activate only non-active accounts. The user table need to get updated to use that features (check the SQL statement above the modified method). It’s possible now to use a third state “blocked” via the admin panel (the method activation_switch() is modified).

Version 1.96

Today a user reported (thanks John Doe 3rd) that for a lot of database queries the class is not safe against SQL injections if magic_quotes_gpc = off. I checked all possible string values and added the function ins_string() to these values. This validation method is not new and was used before for several methods. All users where magic quotes is not configured should update this class or changing the methods where the values entered by the Internet user are send to a database query.

Version 1.95

I removed some default variable definitions from the constructor method because sometimes the variables need different values. In previous version you need to define the vars $user and $user_pw with some extra code, in this version they are automatically declared if the session exists. The new argument $redirect inside the constructor is used for the modified method set_user(), this is used to redirect while using the automatic login function. That will say only if the Boolean inside the method is true the redirect will be processed. The test for the existence of the session vars is removed because it’s not necessary anymore. Inside the profile extension is a constructor now, this has the functions from main class constructor and some extra functions make it easier to use the profile extension. Check also the improved example file update_user_profile.php, the complete process is more compact now. To test if there is am existing profile a new example is used “profile_example.php”, if there is no profile record the user is redirected to the update profile page (check the new constant variable inside the config file). This feature is useful if the user profile is required inside an application.

Version 1.94

In the previous version there was a change to remember an encrypted password and use this value also in the login form. Because the login method needs to accept the raw and the encrypted the password check is less save then in versions before. Because of some complains via the forum I decided to change the cookie bases login process. In this version is the user automatically logged in if a valid cookie exists on the client side. User of this class can disable this feature by setting the variable “save_login” to “no” during the login process. Both login examples are changed and also the methods Access_user(), set_user(), login_reader() and log_out(). Please note also the new created session variable “logged_in”, this can be used on pages with conditional content (if a user is logged in or not).

Version 1.93

There was a small bug inside the login_user() method since the last update, a password stored with the cookie doesn’t work after the first logout, this is fixed. Next Sean informed me that inside the access_page() method that there is no exit command after the redirection code. This could be a problem if inside the protected script some code will be executed after the user check. This is fixed and also the logout method got some exit function after the redirection code. If the the sessions are stored inside the MySQL database you need an object free log-out page to remove the session data from the database. Check the logout example and also the new setting for the logout page inside the config file.

Version 1.92

There are two important changes in this version: 1. It’s possible now to store the session data in your database (this is much safer if you use sessions on a shared hosting server); 2. the password is always MD5 encoded now. For the last one there are several methods changed (check the support forum for details, a link is located on the right site of the access_user class website). Further (small) changes: added session_destroy() to the logout method; the links used in the e-mail messages are double md5-encoded now (check the messages with URL’s in the messages() method). This is a bigger update, I tried my best to test all changes if something is wrong please let me know (post to the forum).

Version 1.91

The variable $access_level is removed, if someone needs the access level value the method get_access_level() must be called. The method returns the access level from a user, the method access_page() is modified to handle this. Inside the example to update the users profile is more example code to show how the different date formats are optimized and processed. The method “create_form_field()” inside the update profile extension is an extra test if a euro-date field is not empty. There was something wrong if the class is used to activate the account by admin only. The system was sending the e-mail to the new user. This is fixed inside the register_user() method, remember to use the variable $auto_activation in the page where the email verification will happen.

Version 1.90

Something went wrong during a update in the past, if the auto-activation was set to “false”, in this case an e- mail was send without subject and message body. This is fixed inside the method activate_account() on row 376. There was also a small bug inside the update_user_profile example file at row 14, inside the arguments of the function there was an error for the last argument. The variable $send_copy has no function in older versions. If this var is set to “true” after account activation a blind copy is send the site’s admin e-mail address.

Version 1.89

Until the last version there was a small bug inside the messages method, while sending a confirmation the login of the administrator shows up. This wrong login is replaced with the value of the real name field (or a default if this is empty). $msg[37] is changed to get the right (real) name inside the conformation e-mail and also the method send_confirmation() is modified. I added also the missing $msg[24] for several languages. Thank you Dan for your question which points me to this not so gentle bug!

Version 1.88

I added two more user fields to the user_profile extension (check also the db_config.php file and update your table). To validate a date to insert/read from the database I changed the method ins_string() from the class source and the profile extension method create_form_field(). The modified ins_string() makes it possible to use an extended string like “some value##date”, the string “date” is recognized by this method as the type. Don’t forget to validate the input first! Used PHP’s date functions like “strftime()” and “strtotime()” for a regular (euro) date output.

Version 1.87

There was only one mail subject and message used by different functions, this was not really clear for users. I’ve split this messages into new strings, affected methods: send_mail(), send_confirmation(), forgot_password() and of course the method messages(). I noticed also a bug if the auto_activation is set to true (always the same kind of text). It’f fixed and the register_user() method is changed.

Version 1.86

There was a small bug inside the method update_user_by_admin() (file: admin_user.php), I fixed this. Please check the extra information about the database table name convention (inside the documentation file). I added and example how to show the real name in place of the login name inside the file example.php.

Version 1.85

There was a small bug if you want to use the class with “auto_activation = false” the method send_mail() is fixed now. Check the new notes inside the help file.

Version 1.84

I noticed some conflicts if you use this class together with tables from a different database. I remove the mysql_select_db command and modified the table names (added the database constant). There is a new method (check_new_password()) to check new passwords against a second conformation password. A new message (38) is used if this check result is false. The modified methods register_user() and update_user. The German and French messages are available now in the Users_profile extension. Thank you Francis for the translation job!

Version 1.83

There was small bug during the update of a new password via the admin page. It’s a BSD style license now!

Version 1.82

In this version the activation and notification functions are more optimized. The sendmail() method can handle more different mail jobs and the activate_account() method will use the new method send_confirmation() to inform the user by mail. There are also some improvements for the user admin function. The class will not send anymore a mail copy to the admin, from now a new mail is send while using the account_activation() method. Notice the new vars inside the db_config file and the modified admin_user.php file.

Version 1.81

Find in this version a function to use this class with manual account validation. To handle these requests, a copy of the activation mail mail is to the site admin (new var, check the db_config.php file. The admin_user.php is more extended to handle an activation status update. From the main class the following methods are changed: send_mail(), activate_account(), messages() and check_email() (optimized regex pattern). Notice the new var inside the login example.

Version 1.80

With this version is it finally possible to work with access levels. Find in this distribution all important examples and also a new application file to change the user data (email, password and access level (admin only)). The methods access_page() and register_user()of the main class are modified. Notice the new method get_access_level() and check the db_config.php file for modifications. Thanks, Alex Hayes for helping with the access levels.

Version 1.78

There was a small bug inside the get_profile_data() method (profile extension), the phone number was totally ignored.

Version 1.77

I removed the method login_reader() from the constructor because this can create problems if the user have more then one account inside the same application. You have to use this method for now inside the login scripts (they are modified too). I also added booleans to the activate_new_password() method to handle wrong (password) entries. I modified the file “activate_password.php” (new hidden field) to hold the login name after submission of the new password and its possible to check that password is not inserted twice.

Version 1.76

Some (not so important) bug fixing in the methods: send_mail() and reg_visit(), check_activation_password() (thanks Tomas, for the reports) and forgot_password() (wrong message). In all URLs, used by the the method messages() for sending e-mails, is the language available since this version (…&language=$this->language). This will help to identify the right lang on multi-language sites.

Version 1.75

In older version there is a security problem if someone know the login name from a other user. While using the word “new” as password it was possible to login. This is fixed, I changed the following methods: check_user(), login_user() and access_page(). Thanks Mike, for reporting this problem.

Version 1.74

If the user change his password and the login data is saved in a cookie before the new password is not updated. I changed this that the cookie is updated too. The update_user() method is changed to handle this.

Version 1.73

After reading some stories about SQL injections I checked this class and updated some queries to make more safe: I changed the “type specifier” inside the following methods: check_user(), update_user(), validate_email(), activate_new_password() and inside the profile extension: save_profile_date() and get_profile_data().

Version 1.72

I moved the definition of important application files into the config file (see constructor). It’s possible to use standard paths for different uses controlled inside the config file. (modified methods are Access_user() and messages()). I hope this will make it much easier… At least messages are translated into french, thanks Yoan!

Version 1.71

There was a small problem after changing the password in the update_user() method. I moved the md5 encoding a little bit to fix this.

Version 1.70

Check for all new features the manual for the “Users_profile” extension.

Version 1.65

Set the value for this variables inside the the db_config file: $table_name, $webmaster_mail, $webmaster_name, $cookie_name, $cookie_path. I also removed some (db related) vars from class because there not really needed. The constants are used directly. I remove the post var for the login because there is no need of this (it’s a session). I modified the method ins_string() to be more flexible for other types of values (integers).

Version 1.64

There was a bug, if one or more users uses the same password. If one of these have forgot the password and uses the forgot password method, than it was possible that the wrong password was updated. The method activate_new_password() is modified to check also the id while updating the password. Inside the check_user() method the “new_pass” case will check the id, the check for active is gone. The method check_activation_password() is changed, too. The activate_password.php file is modified and can handle this new variable. In this version the method for an (updated) e-mail address validation is placed inside the login.php script. This script is used for validation by the e-mail confirmation message.

Version 1.63

In older versions the entered login name could be case insensitive, I changed the check_user() method that the entered login name must be case sensitive. I removed the md5 encrypyion for the password in the login_user() method and added the encryption to get_user_info() and update_user() method because there was a problem if you save the login data in a cookie. I added the new is_cookie boolean to the example scripts to switch the login_saver to on/off. If the user saved his data in a cookie before and he unchecked the remember option the cookie will be destroyed. I modified for this functionality the methods login_user(), login_saver() and login_reader().

Version 1.62

If a user places the class in the root a bad link was produced while sending a mail (forgot password, register user). After the improvements in version 1.61 I didn’t removed the md5 encoding for the current password. After an update the password was encoded the second time. Both bugs are corrected now.

Version 1.61

Changed the md5 encoding to the password in the methods login_user() and get_user_info(), because there was an error reported after updating the account with a new password (the second time). The same time I changed all server variables to fit the configuration with register_globals = off.

Version 1.60

The file manual.txt is replaced with a new better manual, access_user_doc.htm. In this file all important functions are described with examples and explanations about how to use the class. Some of the example pages are little bit changed to fit the manual exactly.

Version 1.51

I modified the update_user() method to take care of an empty password. If the user doesn’t filled the form with a new password the old one will be used during the record update.

Version 1.50

The forgot_password() method is complete replaced with some new functions to use a safer way to handle a forgotten password. Check the new / changed methods: check_user(), forgot_password(), check_activation_password(), activate_new_password(), messages(). Find on the example page (forgot_password.php) only the email field. After submitting the form you get an activation link. After clicking this link you can insert a new password. I placed the connect_db() method inside the constructor, too. There is a new appliciation file: activate_password.php, other file(s) are changed (forgot_password.php)

Version 1.40

Since this release on you have to check for a unique user name too. The following methods are modified: check_user(), messages(), register_user(). I noticed that after updating an account a double e-mail was not checked in the database. Updates methods: update_user(), messages(). The login name can’t be changed anymore.

Version 1.31

I added a function to save the last date of a visit into the extra_info field from the users table. To activate this feature you have set the var $count_visit to true.

Version 1.30

I modified the “access_page” and “set_user” methods to take care of the “referrer” information. With this functions is it possible to remember the address of a page which is requested without login. (see the new example: testpage.php). Notice the new methods “login_saver” and “login_reader”. With this functions is it possible to remember the login information on the client side.

Version 1.20

Now it is possible to update an account, use the new example page (update_user.php). While updating the class I changed the structure of method’s which are called from outside the class. In this version the vars are given to the method and not more predefined. If some one want to update this class for PHP 5 than its possible to separate private vars. Several methods are more flexible than before and I removed some small bugs.

Version 1.10

Added new property: language, together with the new error reporting method is it possible to translate the messages. Im removed the properties $ok_msg and $error_msg, use for now only (the new one) $the_msg.

Version 1.02

New method: get_user_info(), use this to retrieve all user date from the database (to show the visitor his information).

Version 1.01

Added the db_config.php file with some constants for the database connection, this makes the whole more flexible.