HTTP Setting page security using MySQL and PHP. HTTP Setting page security using MySQL and PHP Php simple engine with authentication

In order to send the client's browser a message "Authentication Required", which in turn will lead to a dialog box for entering a username and password. After the client has entered his username and password, the script will be called again, but this time with the predefined variables PHP_AUTH_USER, PHP_AUTH_PW and AUTH_TYPE, which respectively contain the username, password and authentication type. These variables can be found in the $ _SERVER and $ HTTP_SERVER_VARS arrays. Currently only "Basic" authentication is supported. You can also see a more detailed description of the function header () .

An example of a script fragment that forces the client to log in to view the page:

Example HTTP Authentication

if (! isset ($ _ SERVER ["PHP_AUTH_USER"])) (
header ( "WWW-Authenticate: Basic realm \u003d" My Realm "");

echo "The text sent in the event that
if the user pressed the Cancel button "
;
exit;
) else (
echo
"

Hello ($ _SERVER ["PHP_AUTH_USER"]).

" ;
echo "

You entered the password ($ _SERVER ["PHP_AUTH_PW"]).

"
;
}
?>

Compatibility note:Be especially careful when specifying HTTP headers. In order to guarantee maximum compatibility with as many different clients as possible, the word "Basic" must be capitalized "B", the region (realm) must be quoted in double (not single!) Quotes, and exactly one space must precede the code 401 in the title HTTP / 1.0 401 .

Instead of simply displaying the PHP_AUTH_USER and PHP_AUTH_PW variables on the screen, you might want to check that they are correct. To do this, use a database query or search for a user in a dbm file.

You can observe the peculiarities of the Internet Explorer browser. It is very picky about the parameter of the transmitted headers. Specifying a title WWW-Authenticate before sending HTTP / 1.0 401 status is a little trick.

As of PHP 4.3.0, in order to prevent anyone from writing a script to reveal the password for a page that uses external authentication, PHP_AUTH variables are not set if the page uses external authentication and secure mode is set. Regardless, the REMOTE_USER variable can be used to authenticate an externally authenticated user. Thus, you can always use the $ _SERVER ["REMOTE_USER"] variable.

Note:PHP uses the AuthType directive to indicate whether external authentication is used or not.

It should be noted that all of the above does not prevent theft of passwords for pages requiring authorization by anyone who controls unauthorized pages located on the same server.

Both Netscape Navigator and Internet Explorer clear the current window's authentication cache for the specified region (realm) when received from the server. This can be used to implement forced user logout and redisplay the dialog box for entering username and password. Some developers use this to limit authorization by time or to provide a Logout button.

An example of HTTP authentication with forced entry of a new username / password pair

function authenticate () (
header ( "WWW-Authenticate: Basic realm \u003d" Test Authentication System "");
header ("HTTP / 1.0 401 Unauthorized");
echo "You must enter the correct username and password to access the resource \\ n";
exit;
}

If (! Isset ($ _ SERVER ["PHP_AUTH_USER"]) ||
($ _POST ["SeenBefore"] \u003d\u003d 1 && $ _POST ["OldAuth"] \u003d\u003d $ _SERVER ["PHP_AUTH_USER"])) (
authenticate ();
}
else (
echo
"

Welcome: ($ _SERVER ["PHP_AUTH_USER"])
" ;
echo "Previous login: ($ _REQUEST [" OldAuth "])";
echo "

\\ n ";
echo "\\ n ";
echo "\\ n ";
echo "\\ n ";
echo "

\\ n ";
}
?>

This behavior is not regulated by the HTTP Basic Authentication Standards, therefore you should not depend on it. As tests have shown, the Lynx browser does not clear the authorization cache when it receives a 401 status from the server, and by clicking "Back" and then "Forward" it is possible to open such a page, provided that the required authorization attributes have not changed. However, the user can press the "_" key to clear the authentication cache.

It should also be noted that prior to PHP 4.3.3, HTTP authentication did not work on servers running Microsoft IIS if PHP was installed as a CGI module due to some IIS limitation. In order to work correctly in PHP 4.3.3+, you must edit the IIS configuration setting called "Directory Security". Click on "Edit" and set the option "Anonymous Access", all other fields should be unchecked.

Another limitation if you are using IIS over ISAPI: PHP_AUTH_ * variables are not defined, but at the same time the HTTP_AUTHORIZATION variable is available. Example code you could use: list ($ user, $ pw) \u003d explode (":", base64_decode (substr ($ _ SERVER ["HTTP_AUTHORIZATION"], 6)));

Note on IIS ::For HTTP authentication to work correctly in IIS, the cgi.rfc2616_headers option in the PHP configuration must be set to 0 (the default).

Attention:In case protected mode is used, the UID of the current script will be added to the realm part of the WWW-Authenticate header.



<<< Назад Content Forward \u003e\u003e\u003e
If you still have questions or something is not clear - welcome to our

It is possible to use the function header () to send a message "Authentication Required" the browser, forcing it to show a window for entering a username and password. As soon as the user fills in the username and password, the link containing the PHP script will be called again with the predefined PHP_AUTH_USER, PHP_AUTH_PW, and AUTH_TYPE variables set to login, password and authentication type, respectively. These predefined variables are stored in the $ _SERVER and $ HTTP_SERVER_VARS arrays. Both types are supported: "Basic" and "Digest" (since PHP 5.1.0). See function for details header ().

An example of a script fragment that forces the client to log in to view the page:

Example # 1 Basic HTTP Authentication Example

if (! isset ($ _ SERVER ["PHP_AUTH_USER"])) (
header ( "WWW-Authenticate: Basic realm \u003d" My Realm "");

echo "The text sent in the event that
if the user pressed the Cancel button "
;
exit;
) else (
echo
"

Hello ($ _SERVER ["PHP_AUTH_USER"]).

" ;
echo "

You entered your password($ _SERVER ["PHP_AUTH_PW"]).

" ;
}
?>

Example # 2 Digest HTTP Authentication Example

This is a sample implementation of a simple Digest HTTP Authentication script. See RFC 2617 for details.

$ realm \u003d "Restricted Zone";

// user \u003d\u003e password
$ users \u003d array ("admin" \u003d\u003e "mypass", "guest" \u003d\u003e "guest");

if (empty ($ _ SERVER ["PHP_AUTH_DIGEST"])) (
header ("HTTP / 1.1 401 Unauthorized");
header ( "WWW-Authenticate: Digest realm \u003d" "... $ realm.
"", qop \u003d "auth", nonce \u003d "". uniqid (). "", opaque \u003d "". md5 ($ realm). "" ");

Die ( "Text sent when the user clicks the Cancel button");
}

// parse the PHP_AUTH_DIGEST variable
if (! ($ data \u003d http_digest_parse ($ _SERVER ["PHP_AUTH_DIGEST"])) ||
! isset ($ users [$ data ["username"]]))
die ( "Wrong data!");

// generate the correct response
$ A1 \u003d md5 ($ data ["username"]. ":". $ Realm. ":". $ Users [$ data ["username"]]);
$ A2 \u003d md5 ($ _SERVER ["REQUEST_METHOD"]. ":". $ Data ["uri"]);
$ valid_response \u003d md5 ($ A1. ":". $ data ["nonce"]. ":". $ data ["nc"]. ":". $ data ["cnonce"]. ":". $ data ["qop"]. ":". $ A2);

if ($ data ["response"]! \u003d $ valid_response)
die ( "Wrong data!");

// ok, login and password are correct
echo "You are logged in as:". $ data ["username"];

// function to parse the http auth header
function http_digest_parse ($ txt)
{
// protection against missing data
$ needed_parts \u003d array ("nonce" \u003d\u003e 1, "nc" \u003d\u003e 1, "cnonce" \u003d\u003e 1, "qop" \u003d\u003e 1, "username" \u003d\u003e 1, "uri" \u003d\u003e 1, "response" \u003d\u003e 1);
$ data \u003d array ();
$ keys \u003d implode ("|", array_keys ($ needed_parts));

Preg_match_all ("@ (". $ Keys. ") \u003d (?: ([\\" "]) ([^ \\ 2] +?) \\ 2 | ([^ \\ s,] +)) @", $ txt, $ matches, PREG_SET_ORDER);

Foreach ($ matches as $ m) (
$ data [$ m [1]] \u003d $ m [3]? $ m [3]: $ m [4];
unset ($ needed_parts [$ m [1]]);
}

Return $ needed_parts? false: $ data;
}
?>

Comment: Compatibility note

Be especially careful when specifying HTTP headers. In order to guarantee maximum compatibility with as many different clients as possible, the word "Basic" must be capitalized "B", the realm must be enclosed in double (not single!) Quotes, and exactly one space must precede the code 401 in the title HTTP / 1.0 401... Authentication parameters should be separated by commas as shown in the Digest authentication example above.

Instead of simply displaying the PHP_AUTH_USER and PHP_AUTH_PW variables on the screen, you might want to check that they are correct. To do this, use a database query or search for a user in a dbm file.

You can observe the peculiarities of the Internet Explorer browser. It is very picky about the parameter of the transmitted headers. The headline trick WWW-Authenticate before sending status HTTP / 1.0 401 so far works for him.

To prevent someone from writing a script that exposes the password for a page that uses external authentication, PHP_AUTH variables are not set if the page uses external authentication and safe mode is set. Regardless, the REMOTE_USER variable can be used to authenticate an externally authenticated user. Thus, you can always use the $ _SERVER ["REMOTE_USER"] variable.

Comment: Configuration note

PHP uses directive specification AuthType to indicate whether external authentication is used or not.

It should be noted that all of the above does not prevent the theft of passwords for pages requiring authorization by anyone who controls unauthorized pages located on the same server.

Both Netscape Navigator and Internet Explorer clear the current window's authentication cache for the specified region (realm) when receiving a 401 status from the server. This can be used to force a user out and re-display the username and password dialog box. Some developers use this to limit authorization by time or to provide a Logout button.

Example # 3 Example of HTTP authentication with forced entry of a new username / password pair

function authenticate () (
header ( "WWW-Authenticate: Basic realm \u003d" Test Authentication System "");
header ("HTTP / 1.0 401 Unauthorized");
echo "You must enter the correct username and password to access the resource \\ n";
exit;
}

if (! isset ($ _ SERVER ["PHP_AUTH_USER"]) ||
($ _POST ["SeenBefore"] \u003d\u003d 1 && $ _POST ["OldAuth"] \u003d\u003d $ _SERVER ["PHP_AUTH_USER"])) (
authenticate ();
) else (
echo "

Welcome: "... htmlspecialchars ($ _SERVER ["PHP_AUTH_USER"]). "
" ;
echo "Previous login:"... htmlspecialchars ($ _REQUEST ["OldAuth"]);
echo "

\\ n ";
echo "\\ n ";
echo "... htmlspecialchars ($ _SERVER ["PHP_AUTH_USER"]). "\\" /\u003e \\ n ";
echo "\\ n ";
echo "

\\ n ";
}
?>

This behavior is not regulated by the standards HTTP Basic-authentication, therefore, you shouldn't depend on it. Browser testing Lynx showed that Lynx does not clear the authorization cache when receiving the 401 status from the server, and by clicking "Back" and then "Forward" it is possible to open such a page, provided that the required authorization attributes have not changed. However, the user can press the key "_" to clear the authentication cache.

In order for HTTP authentication to work correctly on an IIS server running the CGI version of PHP, you must edit the IIS configuration setting called " Directory Security". Click on the inscription" Edit"and set the option" Anonymous Access", all other fields should be left unchecked.

Comment: IIS note:
For HTTP authentication to work correctly in IIS, in the PHP configuration, the cgi.rfc2616_headers option must be set to 0 (default).

Comment:

In case safe mode is used, the UID of the current script will be added to realm-header part WWW-Authenticate.

Sometimes it is necessary to close it from unauthorized access PHP page if you are making a closed area of \u200b\u200bthe site. It could be some kind of hidden information for your customers or site visitors, some kind of admin interface for you, etc. You can think of hundreds of different tasks requiring access restriction.

You can close such a page in several complementary ways:

  1. Password protection (login / password) using variables $ _SERVER ["PHP_AUTH_USER"] and $ _SERVER ["PHP_AUTH_PW"].
  2. Protection by IP client address using a variable $ _SERVER ["REMOTE_ADDR"].
  3. Protection by MAC address in local networks (in addition to protection by IP).

Let us first analyze the first method, which is the main one. It allows you to close access to the page by login and password, so only people who know the login and password can get access. In addition, they can be divided according to this feature and provide correspondingly different information for each. Implemented by issuing special fields in the protocol header HTTP... Let's create a function auth_send ():

" ,"

Authentication error

" ,"

Contact your administrator to get your login and password.

"," "; exit;);?\u003e

This function tells the browser that it needs login and password authorization to access. And it also gives out a page in Html for the user.

" ,"

Welcome!

" ,"

You are logged in ", $ auth_user," and password ", $ auth_pass,".

" ,"

"; ?>

The login and password verification code is not too complicated in this case, since it is implemented for one person. The logic is simple if there is no variable $ _SERVER ["PHP_AUTH_USER"] and $ _SERVER ["PHP_AUTH_PW"] or their values \u200b\u200bdo not match the required ones, then call the function auth_send ()... Do not forget that it calls at the end exit, so the program is terminated.

The next stage of protection is implemented by filtration IP the addresses of the connecting client. Of course, on the Internet, many providers issue IP addresses for a while and this protection is useless to use, but if we are talking about corporate local networks, then this check will provide additional protection.

Your IP was not found !!! "; exit;);?\u003e

Here in the line $ allowed_ips specified with a space IP addresses that are allowed access. Next, we get the array using explode () and search for the client's address from $ _SERVER ["REMOTE_ADDR"]... I used the function to search array_search (), since its wrong code implemented in C will work somewhat faster than what we can write in PHP using loops for or foreach... But speed is not the main thing here :)

And the last step of defense is checking MAC addresses. It belongs to the category of paranoid and it is worth using it if you get access from the local network and the data that you are protecting is really very important. So far I have implemented this check only on the system Linux, due to the relative ease of implementation. But you can try to implement it for any other platform. We write the function:

As Linux users have already understood, it is based on ARP system table, which can be accessed using the file / proc / net / arp... The function searches the lines for the required IP address and returns it MAC address:

Your IP \u003d 192.168.10.15 and MAC \u003d 00: 04: 31: E4: F8: 37

In system Windows maybe there are also some ways to get MAC simpler, but of those that actually work, this is the conclusion ARP system tables with the command:

C: \\ WINDOWS \\\u003e arp -a Interface: 192.168.10.15 on Interface 0x1000003 IP Address Physical Address Type 192.168.10.1 00-50-22-b0-6a-aa dynamic 192.168.10.2 00-0f-38-68-e9- e8 dynamic 192.168.10.3 00-04-61-9e-26-09 dynamic 192.168.10.5 00-0f-38-6a-b1-18 dynamic

You can implement protection based on this address yourself, if you really need it :) But remember that if you have unmanaged equipment in your network without the possibility of binding MAC addresses to the port, this protection may not work, since you can forge all your identification data used for protection (login, password, IP and MAC address).



Good day friends! Let's take a look at user registration in PHP with you. First, let's define the conditions for our user registration:

  • We encrypt the password using the algorithm MD5
  • The password will be "salted"
  • Check if Login is busy
  • User activation by letter.
  • Writing and storing data in MySQL DBMS

To write this script, we need to understand what user registration is. User registration is the acquisition of real user data, processing and storage of data.

To explain in simple words, registration is just the recording and storage of certain data by which we can authorize the user in our case - this is Login and Password.

Authorization is the granting of a certain person or group of persons the rights to perform certain actions, as well as the process of verifying these rights when trying to perform these actions. Simply put, using authorization, we can delimit access to this or that content on our website.

Let's consider the structure of the script directories for the implementation of our registration with authorization. We need to break scripts into logical components. We have placed the registration and authorization modules in a separate directory. We will also place the connection to the database in separate directories. MySQL, custom function file, style file CSS and our template Html... This structure allows you to quickly navigate the scripts. Imagine you have a large site with tons of modules, etc. and if there is no order, it will be very difficult to find something in such a mess.

Since we will store all data in MySQL DBMS, then let's create a small table in which we will store registration data.

First you need to create a table in the database. The table will be called bez_reg Where bez is the table prefix, and reg table name.

Table structure: bez_reg

- - Table structure `bez_reg` - CREATE TABLE IF NOT EXISTS` bez_reg` (ʻid` int (11) NOT NULL AUTO_INCREMENT, `login` varchar (200) NOT NULL,` pass` varchar (32) NOT NULL , `salt` varchar (32) NOT NULL, ʻactive_hex` varchar (32) NOT NULL,` status` int (1) NOT NULL, PRIMARY KEY (ʻid`)) ENGINE \u003d MyISAM DEFAULT CHARSET \u003d utf8 AUTO_INCREMENT \u003d 1;

Now let's create the main scripts for further work.

INDEX.PHP File

CONFIG.PHP File

"); ?>

404.html file

Error 404

Error 404

A 404 error occurred on the page

To return


BD.PHP File

INDEX.HTML File

PHP MySQL user registration with email activation



FUNCT.PHP File

"." \\ n "; if (is_array ($ data)) (foreach ($ data as $ val) $ err. \u003d"

  • ". $ val."
  • "." \\ n ";) else $ err. \u003d"
  • ". $ data."
  • "." \\ n "; $ err. \u003d""." \\ n "; return $ err;) / ** Simple wrapper for MySQL queries * @param string $ sql * / function mysqlQuery ($ sql) ($ res \u003d mysql_query ($ sql); / * Checking the result This shows the real query sent to MySQL and also the error. Convenient for debugging. * / if (! $ res) ($ message \u003d "Invalid query:". mysql_error (). "\\ n"; $ message. \u003d "Query in full : ". $ sql; die ($ message);) return $ res;) / ** Simple salt generator * @param string $ sql * / function salt () ($ salt \u003d substr (md5 (uniqid ()), - 8); return $ salt;)

    Let's get down to writing registration. First, we will need to make a registration form template so that the user can enter his data for processing. Next, we will need to write the form handler itself, which will check the entered user data for correctness. After the data has been successfully verified, we write them into our database and send a letter to the user to activate his account.

    REG.PHP file

    You have successfully registered! Please activate your account !!"; // We activate the account if (isset ($ _ GET [" key "])) (// Check the key $ sql \u003d" SELECT * FROM `". BEZ_DBPREFIX. "Reg` WHERE ʻactive_hex` \u003d" ". Escape_str ( $ _GET ["key"]). "" "; $ Res \u003d mysqlQuery ($ sql); if (mysql_num_rows ($ res) \u003d\u003d 0) $ err \u003d" The activation key is not correct! "; // Check for errors and display to the user if (count ($ err)\u003e 0) echo showErrorMessage ($ err); else (// Get the user's address $ row \u003d mysql_fetch_assoc ($ res); $ email \u003d $ row ["login"]; // Activate the account user $ sql \u003d "UPDATE` ". BEZ_DBPREFIX." reg` SET `status` \u003d 1 WHERE` login` \u003d "". $ email. "" "; $ res \u003d mysqlQuery ($ sql); // Send an email for activation $ title \u003d "(! LANG: Your account on http: // site has been successfully activated"; $message = "Поздравляю Вас, Ваш аккаунт на http://сайт успешно активирован"; sendMessageMail($email, BEZ_MAIL_AUTOR, $title, $message); /*Перенаправляем пользователя на нужную нам страницу*/ header("Location:". BEZ_HOST ."less/reg/?mode=reg&active=ok"); exit; } } /*Если нажата кнопка на регистрацию, начинаем проверку*/ if(isset($_POST["submit"])) { //Утюжим пришедшие данные if(empty($_POST["email"])) $err = "Поле Email не может быть пустым!"; else { if(!preg_match("/^!} [email protected](+ \\.) + (2,6) $ / i ", $ _POST [" email "])) $ err \u003d" E-mail entered incorrectly "." \\ N ";) if (empty ($ _ POST [ "pass"])) $ err \u003d "Password field cannot be empty"; if (empty ($ _ POST ["pass2"])) $ err \u003d "Password Confirmation field cannot be empty"; // Check for errors and display to the user if (count ($ err)\u003e 0) echo showErrorMessage ($ err); else (/ * Continue checking the entered data Check passwords for matching * / if ($ _ POST ["pass"]! \u003d $ _POST ["pass2" ]) $ err \u003d "Passwords do not match"; // Check for errors and display it to the user if (count ($ err)\u003e 0) echo showErrorMessage ($ err); else (/ * Check if we have such a user in the database * / $ sql \u003d "SELECT` login` FROM `". BEZ_DBPREFIX. "reg` WHERE` login` \u003d "". escape_str ($ _ POST ["email"]). "" "; $ res \u003d mysqlQuery ($ sql); if (mysql_num_rows ($ res)\u003e 0) $ err \u003d "Sorry Login: ". $ _POST [" email "]." busy! "; // Check for errors and display it to the user if (count ($ err)\u003e 0) echo showErrorMessage ($ err); else (// Get the HASH of the salt $ salt \u003d salt (); // Salt the password $ pass \u003d md5 (md5 ($ _ POST ["pass"]). $ salt); / * If all is well, write the data to the database * / $ sql \u003d "INSERT INTO` ". BEZ_DBPREFIX." reg` VALUES ("", "" . escape_str ($ _ POST ["email"]). "", "". $ pass. "", "". $ salt. "", "". md5 ($ salt). "", 0) "; $ res \u003d mysqlQuery ($ sql); // Sending an email to activate $ url \u003d BEZ_HOST. "less / reg /? mode \u003d reg & key \u003d". md5 ($ salt); $ title \u003d "(! LANG: Registration on http: / /website"; $message = "Для активации Вашего акаунта пройдите по ссылке ". $url .""; sendMessageMail($_POST["email"], BEZ_MAIL_AUTOR, $title, $message); //Сбрасываем параметры header("Location:". BEZ_HOST ."less/reg/?mode=reg&status=ok"); exit; } } } } ?>!}

    REG_FORM.HTML File

    PHP MySQL user registration with email activation

    Email *:
    Password *:
    Password confirmation *:

    Fields with an icon * are required

    Since we are ready to register users, it's time to write an authorization. Let's create a form for user authorization, then write an authorization form handler and lastly we will make a script show.php which will show us whether we are authorized in the system or not.

    AUTH.PHP file

    0) echo showErrorMessage ($ err); else (/ * Create a query to fetch from the database to verify the authenticity of the user * / $ sql \u003d "SELECT * FROM` ". BEZ_DBPREFIX." reg` WHERE `login` \u003d" ". escape_str ($ _ POST [" email "]) . "" AND `status` \u003d 1"; $ res \u003d mysqlQuery ($ sql); // If the login matches, check the password if (mysql_num_rows ($ res)\u003e 0) (// Get data from the table $ row \u003d mysql_fetch_assoc ( $ res); if (md5 (md5 ($ _ POST ["pass"]). $ row ["salt"]) \u003d\u003d $ row ["pass"]) ($ _SESSION ["user"] \u003d true; // Reset parameters header ("Location:". BEZ_HOST. "Less / reg /? Mode \u003d auth"); exit;) else echo showErrorMessage ("Wrong password!");) Else echo showErrorMessage ("Login ". $ _POST [" email "]." not found! ");))?\u003e

    For those who have the latest version of PHP, I post this script using PDO since expansion MySQL deprecated and removed from the newer PHP version. Download registration and authorization php mysql pdo

    The archive was updated on February 24, 2015.

    Attention: If you use this script on a local server like DENWER, XAMPP, then you should not wait for letters to your mailbox. Letters are in a blank sendmail... IN Denwer you can find them along the way Z: \\ tmp \\! Sendmail \\ you can open these files in any mail client.

    It is possible to use the function header () to send a message "Authentication Required" the browser, forcing it to show a window for entering a username and password. As soon as the user fills in the username and password, the link containing the PHP script will be called again with the predefined PHP_AUTH_USER, PHP_AUTH_PW, and AUTH_TYPE variables set to login, password and authentication type, respectively. These predefined variables are stored in the $ _SERVER and $ HTTP_SERVER_VARS arrays. Both types are supported: "Basic" and "Digest" (since PHP 5.1.0). See function for details header ().

    An example of a script fragment that forces the client to log in to view the page:

    Example # 6 Basic HTTP Authentication Example

    if (! isset ($ _ SERVER ["PHP_AUTH_USER"])) (
    header ( "WWW-Authenticate: Basic realm \u003d" My Realm "");

    echo "The text sent in the event that
    if the user pressed the Cancel button "
    ;
    exit;
    ) else (
    echo
    "

    Hello ($ _SERVER ["PHP_AUTH_USER"]).

    " ;
    echo "

    You entered your password($ _SERVER ["PHP_AUTH_PW"]).

    " ;
    }
    ?>

    Example # 7 Digest HTTP Authentication Example

    This is a sample implementation of a simple Digest HTTP Authentication script. See RFC 2617 for details.

    $ realm \u003d "Restricted Zone";

    // user \u003d\u003e password
    $ users \u003d array ("admin" \u003d\u003e "mypass", "guest" \u003d\u003e "guest");

    if (empty ($ _ SERVER ["PHP_AUTH_DIGEST"])) (
    header ("HTTP / 1.1 401 Unauthorized");
    header ( "WWW-Authenticate: Digest realm \u003d" "... $ realm.
    "", qop \u003d "auth", nonce \u003d "". uniqid (). "", opaque \u003d "". md5 ($ realm). "" ");

    Die ( "Text sent if user clicked Cancel");
    }

    // parse the PHP_AUTH_DIGEST variable
    if (! ($ data \u003d http_digest_parse ($ _SERVER ["PHP_AUTH_DIGEST"])) ||
    ! isset ($ users [$ data ["username"]]))
    die ( "Wrong data!");

    // generate the correct response
    $ A1 \u003d md5 ($ data ["username"]. ":". $ Realm. ":". $ Users [$ data ["username"]]);
    $ A2 \u003d md5 ($ _SERVER ["REQUEST_METHOD"]. ":". $ Data ["uri"]);
    $ valid_response \u003d md5 ($ A1. ":". $ data ["nonce"]. ":". $ data ["nc"]. ":". $ data ["cnonce"]. ":". $ data ["qop"]. ":". $ A2);

    if ($ data ["response"]! \u003d $ valid_response)
    die ( "Wrong data!");

    // ok, login and password are correct
    echo "You are logged in as:". $ data ["username"];

    // function to parse the http auth header
    function http_digest_parse ($ txt)
    {
    // protection against missing data
    $ needed_parts \u003d array ("nonce" \u003d\u003e 1, "nc" \u003d\u003e 1, "cnonce" \u003d\u003e 1, "qop" \u003d\u003e 1, "username" \u003d\u003e 1, "uri" \u003d\u003e 1, "response" \u003d\u003e 1);
    $ data \u003d array ();
    $ keys \u003d implode ("|", array_keys ($ needed_parts));

    Preg_match_all ("@ (". $ Keys. ") \u003d (?: ([\\" "]) ([^ \\ 2] +?) \\ 2 | ([^ \\ s,] +)) @", $ txt, $ matches, PREG_SET_ORDER);

    Foreach ($ matches as $ m) (
    $ data [$ m [1]] \u003d $ m [3]? $ m [3]: $ m [4];
    unset ($ needed_parts [$ m [1]]);
    }

    Return $ needed_parts? false: $ data;
    }
    ?>

    Comment: Compatibility note

    Be especially careful when specifying HTTP headers. In order to guarantee maximum compatibility with as many different clients as possible, the word "Basic" must be capitalized "B", the realm must be enclosed in double (not single!) Quotes, and exactly one space must precede the code 401 in the title HTTP / 1.0 401... Authentication parameters should be separated by commas as shown in the Digest authentication example above.

    Instead of simply displaying the PHP_AUTH_USER and PHP_AUTH_PW variables on the screen, you might want to check that they are correct. To do this, use a database query or search for a user in a dbm file.

    You can observe the peculiarities of the Internet Explorer browser. It is very picky about the parameter of the transmitted headers. The headline trick WWW-Authenticate before sending status HTTP / 1.0 401 so far works for him.

    As of PHP 4.3.0, in order to prevent anyone from writing a script to reveal the password for a page that uses external authentication, PHP_AUTH variables are not set if the page uses external authentication and secure mode is set. Regardless, the REMOTE_USER variable can be used to authenticate an externally authenticated user. Thus, you can always use the $ _SERVER ["REMOTE_USER"] variable.

    Comment: Configuration note

    PHP uses directive specification AuthType to indicate whether external authentication is used or not.

    It should be noted that all of the above does not prevent the theft of passwords for pages requiring authorization by anyone who controls unauthorized pages located on the same server.

    Both Netscape Navigator and Internet Explorer clear the current window's authentication cache for the specified realm when received from the server. This can be used to implement forced user logout and redisplay the dialog box for entering username and password. Some developers use this to limit authorization by time or to provide a Logout button.

    Example # 8 Example of HTTP authentication with forced entry of a new username / password pair

    function authenticate () (
    header ( "WWW-Authenticate: Basic realm \u003d" Test Authentication System "");
    header ("HTTP / 1.0 401 Unauthorized");
    echo "You must enter the correct username and password to access the resource \\ n";
    exit;
    }

    if (! isset ($ _ SERVER ["PHP_AUTH_USER"]) ||
    ($ _POST ["SeenBefore"] \u003d\u003d 1 && $ _POST ["OldAuth"] \u003d\u003d $ _SERVER ["PHP_AUTH_USER"])) (
    authenticate ();
    ) else (
    echo "

    Welcome: "... htmlspecialchars ($ _SERVER ["PHP_AUTH_USER"]). "
    " ;
    echo "Previous login:"... htmlspecialchars ($ _REQUEST ["OldAuth"]);
    echo "

    \\ n ";
    echo "\\ n ";
    echo "... htmlspecialchars ($ _SERVER ["PHP_AUTH_USER"]). "\\" /\u003e \\ n ";
    echo "\\ n ";
    echo "

    \\ n ";
    }
    ?>

    This behavior is not regulated by the standards HTTP Basic-authentication, therefore, you shouldn't depend on it. Browser testing Lynx showed that Lynx does not clear the authorization cache when receiving the 401 status from the server, and by clicking "Back" and then "Forward" it is possible to open such a page, provided that the required authorization attributes have not changed. However, the user can press the key "_" to clear the authentication cache.

    It should also be noted that prior to PHP 4.3.3, HTTP authentication did not work on servers running Microsoft IIS if PHP was installed as a CGI module due to some IIS limitations. In order to work correctly in PHP 4.3.3+, you must edit the IIS configuration setting called " Directory Security". Click on the inscription" Edit"and set the option" Anonymous Access", all other fields should be left unchecked.

    Another limitation if you are using IIS over ISAPI and PHP 4: variables PHP_AUTH_ * not defined, but at the same time a variable is available HTTP_AUTHORIZATION... Sample code you could use: list ($ user, $ pw) \u003d explode (":", base64_decode (substr ($ _ SERVER ["HTTP_AUTHORIZATION"], 6)));

    Comment: IIS note:
    For HTTP authentication to work correctly in IIS, in the PHP configuration, the cgi.rfc2616_headers option must be set to 0 (default).

    Comment:

    In case safe mode is used, the UID of the current script will be added to realm-header part WWW-Authenticate.

    Did you like the article? To share with friends: