a digression the next feature of programming http clients that we will consider is user...
TRANSCRIPT
A digression
• The next feature of programming HTTP clients that we will consider is user authentication
• Before considering that, however, we will digress to consider a commonly-used user authentication technique
Basic HTTP Authentication • Before giving a document to a client,
– a HTTP server looks for access-control files in every directory of the path to the document
– if it finds one, it only serves the document to the client if the client can prove entitlement
• By default, the access-control files are called .htaccess
• But, in Apache-style servers at least, a list of names for such files can be specified using the AccessFileName directive when configuring the server
(See http://httpd.apache.org/docs/1.3/mod/core.html#accessfilename )
Basic HTTP Authentication (contd.) • To use Basic HTTP Authentication to control access to a directory
and its sub-directories,– create, in the directory, a file with one of the names specified in
the AccessFileName directive• normally, this means a file called .htaccess
– At its simplest, the contents of the file will look like this:AuthName "Some string to name this restricted area"
AuthType Basic
AuthUserFile path/to/some/password/file
require user valid-user
• This specifies • that only a client which can identify itself according to the password
file should be given access to this directory and its contents
• a name for the restricted area of the disk -- this name will be given to the client trying to access any file in this part of the disk, to help remind it of the right name+password to use
Basic HTTP Authentication (contd.) • Suppose I want to protect all contents of the directory
http://www.cs.ucc.ie/j.bowen/cs4408/resources/demosecure/
• I could place in that directory a .htaccess file containing:AuthName "This info is restricted to CS 4408 students"
AuthType Basic
AuthUserFile /www/docs/j.bowen/cs4408/resources/.htpasswd
require user valid-user
• Then I would use the htpasswd utility provided by Apache to insert names+passwords for all eligible people into a file called .htpasswd in the parent resources directory
• Any person trying to use a browser to access this directory would receive this challenge window:
Basic HTTP Authentication (contd.)
• If the user fails to provide acceptable authentication,
he/she would receive the screen shown on the bottom right
Using MSIE to try to get a document from this directory
• Suppose we put a copy of showRequest2.php in this directory
• Suppose we try to use Microsoft Internet Explorer to try to read the output from showRequest2.php
• Suppose we fail to provide the correct password• We get the page shown below
A "home-made browser" which attempts to get the same output
• Now suppose this "home-made" browser tries to read the same file
http://cosmos.ucc.ie/~jabowen/cs4408/myBrowser6.php <?php
require_once "HTTP/Request.php";
$req = &new HTTP_Request("http://www.cs.ucc.ie/j.bowen/cs4408/resources/demosecure/showRequest2.php");
if (!PEAR::isError($req->sendRequest()))
{ echo "<br><strong style='color:red'>Headers</strong>";
$headers = $req->getResponseHeader();
foreach ($headers as $name => $value) { echo "<br> $name = $value"; }
echo "<br><strong style='color:red'>Cookies</strong><br>";
$cookies = $req->getResponseCookies();
foreach ($cookies as $fields)
{ foreach ($fields as $name => $value) { echo "$name = $value; "; }echo "<br>"; }
$contents= $req->getResponseBody();
echo "<br><strong style='color:red'>Body</strong><br>";
echo $contents;
}?>
Results of running this "browser"
• The response contains a WWW-Authenticate header, which specifies that Basic authentication is in force for this disk area, a "realm" called "This info is restricted to CS 4408 students"
• The message body contains the HTML page that we got when we tried to use Microsoft Internet Explorer
A "browser" which provides authentication for this realm
• At http://cosmos.ucc.ie/~jabowen/cs4408/myBrowser7.php<?php
require_once "HTTP/Request.php";
$req = &new HTTP_Request("http://www.cs.ucc.ie/j.bowen/cs4408/resources/demosecure/showRequest2.php");
$req->setBasicAuth("peadar", "foo");if (!PEAR::isError($req->sendRequest()))
{ echo "<br><strong style='color:red'>Headers</strong>";
$headers = $req->getResponseHeader();
foreach ($headers as $name => $value) { echo "<br> $name = $value"; }
echo "<br><strong style='color:red'>Cookies</strong><br>";
$cookies = $req->getResponseCookies();
foreach ($cookies as $fields)
{ foreach ($fields as $name => $value) { echo "$name = $value; "; }echo "<br>"; }
$contents= $req->getResponseBody();
echo "<br><strong style='color:red'>Body</strong><br>";
echo $contents;
}?>
Results of running this "browser"
• Request is accepted -- user+password are in SERVER vars
$PHP_AUTH_USER, $PHP_AUTH_PW which we saw, last year, when we did server-side user-authentication in a PHP program
Another Approach to authentication
• Instead of depending on the server demon to defend directories, we can– make our own programs defend themselves
on a program-by-program basis
PHP-based handling of passwords on both client-side and server-side
• We have just seen how to program a client to send a user+password
• Last year, we saw how to write a server-side PHP program which demanded that the client authenticate itself
• Let's revise that and see how we can use PHP for both sides of the authentication process
Server-side User-authentication in PHP
• A server-side program can use the header() function to send headers requiring authentication
– This will cause a browser to pop up a username/password/realm dialog window and
– When the values have been provided by the user, the browser will send a new request back to the same page containing the appropriate information
– When ther, some special PHP variables will be set:
$PHP_AUTH_USER or $_SERVER["PHP_AUTH_USER"]
$PHP_AUTH_PW or $_SERVER["PHP_AUTH_PW"]
User-authentication in PHP (contd.)
• Consider the following program which is here:
http://www.cs.ucc.ie/j.bowen/cs4408/resources/securePage.php
<?php
if ( ($_SERVER["PHP_AUTH_USER"]=='pedro') &&
($_SERVER["PHP_AUTH_PW"]=='qwerty') )
{ echo "<h1>Welcome</h1>"; }
else
{header("HTTP/1.0 401 Unauthorized");
header("WWW-Authenticate: Basic realm=BankAccounts");
echo "<h1>You must identify yourself</h1>";
echo "<p>Please provide a correct user+password</p>";
}
?>
cs 4408 got here on 14 nov 2005
Accessing this program through a normal browser
• When first called by the browser, no user name or password is provided
• When the WWW-Authenticate header is received by the browser, it asks the user for a username+password
• If he gets it right, he is welcomed
• Otherwise, he is told to that he must identify himself as a user who is entitled to visit the page
A "browser" which provides wrong details for this realm
• At http://cosmos.ucc.ie/~jabowen/cs4408/myBrowser8.php<?php
require_once "HTTP/Request.php";$req = &new HTTP_Request("http://www.cs.ucc.ie/j.bowen/cs4408/resources/securePage.php");
$req->setBasicAuth("peader", "foo");
if (!PEAR::isError($req->sendRequest()))
{echo "<br><strong style='color:red'>Headers</strong>";
$headers = $req->getResponseHeader();
foreach ($headers as $name => $value)
{ echo "<br> $name = $value"; }
echo "<br><strong style='color:red'>Cookies</strong><br>";
$cookies = $req->getResponseCookies();
foreach ($cookies as $fields)
{ foreach ($fields as $name => $value) { echo "$name = $value; "; } echo "<br>"; }
$contents= $req->getResponseBody();
echo "<br><strong style='color:red'>Body</strong><br>";
echo $contents;
}?>
Results of running this "browser"
• Request is rejected because of wrong username and password
A "browser" which provides correct details for this realm
• At http://cosmos.ucc.ie/~jabowen/cs4408/myBrowser9.php<?php
require_once "HTTP/Request.php";$req = &new HTTP_Request("http://www.cs.ucc.ie/j.bowen/cs4408/resources/securePage.php");
$req->setBasicAuth("pedro", "qwerty");
if (!PEAR::isError($req->sendRequest()))
{echo "<br><strong style='color:red'>Headers</strong>";
$headers = $req->getResponseHeader();
foreach ($headers as $name => $value)
{ echo "<br> $name = $value"; }
echo "<br><strong style='color:red'>Cookies</strong><br>";
$cookies = $req->getResponseCookies();
foreach ($cookies as $fields)
{ foreach ($fields as $name => $value) { echo "$name = $value; "; } echo "<br>"; }
$contents= $req->getResponseBody();
echo "<br><strong style='color:red'>Body</strong><br>";
echo $contents;
}?>
Results of running this "browser"
• Request is accepted
User-authentication in PHP (contd.)
• Remember that you cannot mix self-provision of user authentication with external user authentication
• The PHP_AUTH variables will not be set if external authentication is also enabled for a directory which contains a PHP program that is trying to do self-provision of user authentication
– This is to avoid trhe possibility that a script might reveals the password for a page that was protected through a traditional external mechanism, such as the .htaccess mechanism
Using proxies
• HTTP supports both direct and indirect connections between servers and clients
• Indirect connections transmit the request/response messages through one or more proxies
Using proxies (contd.)
• This program, at http://cosmos.ucc.ie/~jabowen/cs4408/myBrowser201.php
uses a direct connection to the RTE server:<?php
require_once "HTTP/Request.php";
$req = & new HTTP_Request('http://www.rte.ie/');
if (!PEAR::isError($req->sendRequest()))
{ $contents= $req->getResponseBody();
echo $contents;}
?>
Output from running this program
Using proxies (contd.)
• This program, at http://cosmos.ucc.ie/~jabowen/cs4408/myBrowser202.php
asks a proxy server to pass its request to the RTE server:
<?php
require_once "HTTP/Request.php";
$req = & new HTTP_Request('http://www.rte.ie/');
$req->setProxy("csproxy.ucc.ie", 80);
if (!PEAR::isError($req->sendRequest()))
{ $contents= $req->getResponseBody();
echo $contents;}
?>
Output from running this program
Uploading files
• Last year, we saw how to write PHP programs which would accept files being uploaded from a browser
• We will review that material before going on to see how we can write our own clients to upload files to servers
File upload form<html><head><title>Upload a File</title></head><body><h1>Upload a File</h1>
<form enctype="multipart/form-data" method="post" action="uploadFile.php">
<p>File to Upload:<input type="file" name=“file1" size="30"></p>
<p><button input type="submit“> "Upload File“</button></p>
</form></body></html>
File upload script<html><head><title>File Upload Report</title></head><body><h1>File Upload Report</h1><p><?phpif ( $file1_name != ‘’ ) { copy("$file1 ", "/full/path/to/your/target/directory/$file1_name") or die(“Could not copy the file! Are directory permissions correct? </p></body></html>");
echo “The following file has been received: “; echo “$file1_name containing $file1_size bytes and of MIME type $file1_type"; } else { die(“You did not specify an input file </p></body></html> "); } ?></p></body></html>
Newer convention
• Newer versions of PHP store all the uploaded file information in the $_FILES autoglobal array.
• $_FILES['userfile']['name'] – The original name of the file on the client machine.
• $_FILES['userfile']['type'] – The mime type of the file, if the browser provided this
information. An example would be `"image/gif"`. • $_FILES['userfile']['size']
– The size, in bytes, of the uploaded file. • $_FILES['userfile']['tmp_name']
– The temporary filename of the file in which the uploaded file was stored on the server.
Part 1 of newer version of program• Program available at:
http://www.cs.ucc.ie/j.bowen/cs4408/resources/fileUploader.php
• It will only work if it has write permission for directory /www/docs/j.bowen/cs4408/resources/upload/
<html>
<head><title>File uploader</title></head>
<body>
<?php
if (!$_POST["uploadingFile"])
{ ?><h1>Upload a File</h1>
<form enctype="multipart/form-data" method="post" action="fileUploader.php">
<p>File to Upload:
<input type="file" name="file1" size="30"></p>
<input type="hidden" name="uploadingFile" value="1">
<p><button input type="submit">Upload File</button></p>
</form>
<?php
}
Part 2 of newer version of program
else {?> <h1>File Upload Report</h1><p>
<?php $file1_name=$_FILES["file1"]["name"];
$file1_type=$_FILES["file1"]["type"];
$file1_size=$_FILES["file1"]["size"];
$file1=$_FILES["file1"]["tmp_name"];
if ( $file1_name != "" ) { $uploadDirectory = '/www/docs/j.bowen/cs4408/resources/upload/';
$destinationFile= $uploadDirectory.$file1_name;
move_uploaded_file($file1, $destinationFile) or die("Could not copy the file! Are directory permissions correct?");
?>The following file has been received: <?php echo $file1_name; ?> containing <?php echo $file1_size; ?>
bytes and of MIME type <?php echo $file1_type; ?><?php
}
else { die("You did not specify an input file </p>"); } ?>
<?php } ?>
</p></body></html>
Program in use with a MSIE browser
Program in use with a MSIE browser
Program in use with a MSIE browser
Program in use with a MSIE browser
Program in use with a MSIE browser
Program in use with a MSIE browser
A client which uploads a file to the same program • Suppose we want to write our own client which will upload a file to
this program:
http://www.cs.ucc.ie/j.bowen/cs4408/resources/fileUploader.php
• Remember that the program fileUploader.php expects to receive data from a form on which there are the following input boxes:
<input type="file" name="file1" size="30">
<input type="hidden" name="uploadingFile" value="1">
• Our client must send a request which contains data that looks as if it comes from these two inputs
• That it, it must send, as POST data, the equationuploadingFile=1
• and it must send a file as it it were sent from a file input called file1
A client which uploads a file to the same program • This client is available here
http://cosmos.ucc.ie/~jabowen/cs4408/myBrowser10.php
• It uploads a file called courses.txt from a sub-directory, called demoDir, of the directory which contains the client program itself
<?php
require_once "HTTP/Request.php";
$req =& new HTTP_Request("http://www.cs.ucc.ie/j.bowen/cs4408/resources/fileUploader.php");
$req->setMethod(HTTP_REQUEST_METHOD_POST);
$req->addPostData("uploadingFile", "1");
$result = $req->addFile("file1", "demoDir/courses.txt");
if (!PEAR::isError($result))
{ $response = $req->sendRequest();
if (!PEAR::isError($response)) { echo $req->getResponseBody(); }
} ?>
Result of running this client