Lecture 6 Session Control and User Authentication INLS 760 Web Databases Spring 2013 Rob Capra
HTML Forms and PHP PHP: lect2/form1.php echo "Hello, ". htmlspecialchars(strip_tags($_get['name'])); echo "<br>"; echo "You are in the course: ". htmlspecialchars(strip_tags($_get['course'])); 2
Simple PHP page protection Simple page protection lect6/onepage.php (based on Ch.16, p.360-361) $user = $_POST['user']; $pass = $_POST['pass']; if (empty($user) empty($pass)) { You must log in to see this page.<p> <form method="post" action="onepage.php"> Username: <input type="text" name="user"><p> Password: <input type="password" name="pass"><p> <input type="submit" value="login"> </form> else if ($user=='inls760' && $pass=='foo') { echo "Here is the hidden page.<p>"; else { echo "Incorrect username / password."; Note 1: This is all done in one file. Note 2: What if $user='inls760' Instead of == Note 3: @ suppresses any errors 3
User input Do NOT trust ANY user input How we handle user input depends on what we wish to do with it. Common things: Store in a database (e.g. name, address) Display in HTML (back to the user, or to other users) Compare against a stored value (e.g. logging in) 4
Sanitizing User Input if ($_GET['sortby']) { $sortby = $_GET['sortby']; else { $sortby = "itemnum"; echo "sortby = $sortby"; 5
Sanitizing User Input $sortby = "itemnum"; switch ($_GET['sortby']) { case "author": $sortby = "author"; break; default: $sortby = "itemnum"; echo "sortby = $sortby"; Four points: 1. Clear initialization of $sortby variable at the top of the code segment 2. switch statement avoids = versus == mistakes 3. Assigns $sortby a known value in each case 4. Includes a default in the switch QTP: Which assignment statement is last when there is no sortby passed through the GET? 6
myaddslashes() lect6/myaddslashes.php function myaddslashes($s,$db) { $retval = $s; if (get_magic_quotes_gpc()) { $retval = stripslashes($retval); $retval=mysql_real_escape_string($retval,$db); return $retval; See Best Practices: http://us.php.net/manual/en/function.mysql-real-escape-string.php 7
When do we use...? mysql_real_escape_string() addslashes htmlentities html_specialchars() strip_tags()
Future Assignments Future Assignments starting with Project 3 Initialize ALL variables clearly at the top of code segments Appropriate use of addslashes, striptags, htmlentities Conditional code for magicquotes_gpc ON or OFF\ Should each have their own version of the records database (e.g. p4records, p5records, etc.) 9
Avoid using eval() PHP eval() evaluates its argument as PHP code and returns the result. X eval("\$foo = 1+1;"); echo $foo; As a general rule, NEVER use eval() Especially not with user input!!! 10
What is session control? HTTP is stateless So Session Control How do we keep track of users across multiple pages? Answer: Session control / management 11
Session control How? Session ID Unique key to identify each session (e.g. 8c6ea32b1) Web site example, visit sites, look at cookies/sids Cookies Small name-value pair of information stored at the client, placed by the server Can be used to store a session id Pass-along in URLs (get method) Alternate to storing SID in a cookie Pass SID in each URLs: foo.php?8c6ea32b1 http://us2.php.net/manual/en/session.idpassing.php Examples: Amazon includes the sessionid in the URL 12
Session control in practice Look at session and cookie information from several commercial web sites PHPSESSID 13
Session variables and PHP First, read (especially sessions and security): http://us2.php.net/manual/en/ref.session.php Look at session settings on ruby Start a session in PHP session_start(); Session variables In addition to the session id, you may want to store other information for use during a session PHP superglobal $_SESSION Stores variables across an entire session $_SESSION['foo'] = 760; 14
Session variables and PHP session_start(); $sid = session_id(); echo "The SID for this session is ". $sid. "<br>"; $_SESSION['itemsincart'] = 5; echo "itemsincart = ". $_SESSION['itemsincart']. "<br>"; <a href="session2.php">go to next session example page</a> lect6/session1.php lect6/session2.php session_start(); $sid = session_id(); echo "The SID for this session is ". $sid. "<br>"; echo "itemsincart = ". $_SESSION['itemsincart']. "<br>"; unset($_session['itemsincart']); $_SESSION = array(); session_destroy(); <a href="session3.php">go to next session example page</a> 15
Session variables and PHP lect6/session3.php session_start(); $sid = session_id(); echo "The SID for this session is ". $sid. "<br>"; echo "itemsincart = ". $_SESSION['itemsincart']. "<br>"; Problem: Session id is still stored QTP: Look at browser cookies should be able to see PHPSESSID, but why is that all that is stored? What about itemsincart? 16
Session variables and PHP Completely destroying sessions can get tricky Recall that session ids can be Stored in a cookie Passed along in the URLs To get rid of a session id when passing along can stop passing along To get rid of a session id when using cookies session_destroy() does not delete the session id cookie Must remove session id cookie manually Several approaches Cookies aren t really removed, but rather, they expire See: http://us3.php.net/manual/en/function.session-destroy.php 17
Session variables and PHP session_start(); $sid = session_id(); echo "The SID for this session is ". $sid. "<br>"; $_SESSION['itemsincart'] = 5; echo "itemsincart = ". $_SESSION['itemsincart']. "<br>"; <a href="session2b.php">go to next session example page</a> lect6/session1b.php lect6/session2b.php session_start(); $sid = session_id(); unset($_session['itemsincart']); $_SESSION = array(); if (isset($_cookie[session_name()])) { setcookie(session_name(), '', time()-42000, '/'); session_destroy(); echo "The SID for this session is ". $sid. "<br>"; echo "itemsincart = ". $_SESSION['itemsincart']. "<br>"; <a href="session3b.php">go to next session example page</a> Note that setcookie must happen *before* other output since it is part of the headers: http://us3.php.net/manual/en/function.setcookie.php 18
Session variables and PHP lect6/session3b.php session_start(); $sid = session_id(); echo "The SID for this session is ". $sid. "<br>"; echo "itemsincart = ". $_SESSION['itemsincart']. "<br>"; There are other approaches to handle the session id cookie See: http://us3.php.net/manual/en/function.session-destroy.php 19
Sessions for User Accounts Sessions are a convenient way to handle user accounts for a web site Idea: Store account information in MySQL User logs in using a form Verify username and password Set session variables to indicate logged in 20
Encryption in PHP Safer alternative to storing account passwords in plain text Use a one-way hashing algorithm md5, sha1 Instead of if ($enteredpass == $plaintextstoredpass) Use this if (sha1($enteredpass) == $sha1storedpass) 21
Encryption in PHP PHP sha1() function lect6/sha1.php echo sha1('mypassword'); Output is: 91dfd9ddb4198affc5c194cd8ce6d338fde470e2 22
Using sha1 in PHP & MySQL lect6/sha1.php $plaintext = $argv[1]; $ciphertext = sha1($plaintext); echo "plaintext = ###". $plaintext. "###\n"; echo "ciphertext = ###". $ciphertext. "###\n"; echo "sha1('password') = ###". sha1('password'). "###\n"; // check in mysql with // select sha1('password'); In MySQL: select sha1('password'); 23
Set up user accounts in DB mysql> create table swusers -> (uid int unsigned not null auto_increment primary key, -> uname varchar(20), upass varchar(50), utype varchar(20)); mysql> insert into swusers values (NULL, 'luke', sha1('ekul'), 'jedi'); mysql> insert into swusers values (NULL, 'ben', sha1('neb'), 'jedi'); mysql> insert into swusers values (NULL, 'yoda', sha1('adoy'), 'jedimaster'); mysql> select * from swusers; +-----+-------+------------------------------------------+------------+ uid uname upass utype +-----+-------+------------------------------------------+------------+ 2 luke cf3bda53706bd12c766d2e00c0f823d698101ca3 jedi 3 ben 33ec049c8ac6227a8869e91c3cdbbec90bbac265 jedi 4 yoda e12c0bef5a1409e7843fbab98fe4b176aee8441a jedimaster +-----+-------+------------------------------------------+------------+ 3 rows in set (0.00 sec) 24
Authentication + Session Control lect6/swcantina-home.php <h1>sw Cantina</h1> <form method="post" action="swcantina-login.php"> Username: <input type="text" name="fuser"><p> Password: <input type="password" name="fpass"><p> <input type="submit" value="login"> </form> 25
Login lect6/swcantina-login.php (part 1 of the file) if (isset($_post['fuser']) && isset($_post['fpass'])) { // user has provided a username & password, so try to log them in $fuser = $_POST['fuser']; $fpass = $_POST['fpass']; require "/export/home/r/rcapra/dbconnect.php"; //echo mysql_error($db); $query = 'select utype from swusers '. "where uname = '$fuser' ". "and upass = sha1('$fpass')"; //echo "query = $query". "<br>"; $result = mysql_query($query); //echo mysql_error($db); $num_rows = mysql_num_rows($result); if ($num_rows > 0) { session_start(); $row = mysql_fetch_row($result); echo "###$row[0]###<br>"; $_SESSION['valid_user'] = $fuser; $_SESSION['user_type'] = $row[0]; mysql_close($db); 26
Login lect6/swcantina-login.php (part 2 of the file) <h1>login Page</h1> if (isset($_session['valid_user'])) { // user is logged in echo 'Welcome, '. $_SESSION['valid_user']. '<br>'; echo '<a href="swcantina-logout.php">logout</a><br>'; if ($_SESSION['user_type'] == 'jedi') { echo '<a href="swcantina-jedi.php">jedi only</a><br>'; echo '<a href="swcantina-jedimaster.php">jedi master only</a><br>'; if ($_SESSION['user_type'] == 'jedimaster') { echo '<a href="swcantina-jedi.php">jedi only</a><br>'; echo '<a href="swcantina-jedimaster.php">jedi master only</a><br>'; else { // user is not logged in if (isset($fuser)) { // tried to login, but failed echo "Problem logging in.<br>"; else { // not logged in echo "You are not logged in.<br>"; <h1>sw Cantina</h1>Please log in. <form method="post" action="swcantina-login.php"> Username: <input type="text" name="fuser"><p> Password: <input type="password" name="fpass"><p> <input type="submit" value="login"> </form> 27
if (isset($_post['fuser']) && isset($_post['fpass'])) { // user has provided a username and password, // so try to log them in $fuser = $_POST['fuser']; $fpass = $_POST['fpass']; require "/export/home/r/rcapra/dbconnect.php"; //echo mysql_error($db); $query = 'select utype from swusers. "where uname = '$fuser' ". "and upass = sha1('$fpass')"; //echo "query = $query". "<br>"; $result = mysql_query($query); //echo mysql_error($db); $num_rows = mysql_num_rows($result); if ($num_rows > 0) { session_start(); $row = mysql_fetch_row($result); echo "###$row[0]###<br>"; $_SESSION['valid_user'] = $fuser; $_SESSION['user_type'] = $row[0]; mysql_close($db); <h1>login Page</h1> Login lect6/swcantina-login.php (whole file) if (isset($_session['valid_user'])) { // user is logged in echo 'Welcome, '. $_SESSION['valid_user']. '<br>'; echo '<a href="swcantina-logout.php">logout</a><br>'; if ($_SESSION['user_type'] == 'jedi') { echo '<a href="swcantina-jedi.php">jedi only</a><br>'; echo '<a href="swcantina-jedimaster.php">'; echo 'Jedi master only</a><br>'; if ($_SESSION['user_type'] == 'jedimaster') { echo '<a href="swcantina-jedi.php">jedi only</a><br>'; echo '<a href="swcantina-jedimaster.php">'; echo 'Jedi master only</a><br>'; else { // user is not logged in if (isset($fuser)) { // tried to login, but failed echo "Problem logging in.<br>"; else { // not logged in echo "You are not logged in.<br>"; <h1>sw Cantina</h1> Please log in. <form method="post" action="swcantina-login.php"> Username: <input type="text" name="fuser"><p> Password: <input type="password" name="fpass"><p> <input type="submit" value="login"> </form> 28
Standard dbconnection /export/home/r/rcapra/dbconnect.php -rw-r r-- $h = 'pearl.ils.unc.edu'; $u = 'webdb_1'; $p = 'yourpassword'; $dbname = 'webdb_1'; $db = mysql_connect($h,$u,$p) or die('could not connect'); mysql_select_db($dbname) or die ('Could not select db'); lect3/showdb2.php -rw-r r-- echo "SW Cantina Products<p>"; require "/export/home/r/rcapra/dbconnect.php"; $query = "select * from swcantina"; $result = mysql_query($query); while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) { echo $row['pname']. " ($". $row['price']. ") -- ". $row['pdesc']; echo "<p>"; 29
Debugging PHP Illustrate debugging swcantina-login.php session_start() warning about already output headers Why? extra line at end of dbconnect.php 30
lect6/swcantina-logout.php Logout session_start(); $old_user = $_SESSION['valid_user']; $_SESSION = array(); if (isset($_cookie[session_name()])) { setcookie(session_name(), '', time()-42000, '/'); session_destroy(); <h1>logout</h1> if (!empty($old_user)) { echo "You are now logged out.<br>"; else { echo "You were not logged in.<br>"; <a href="swcantina-home.php>home page</a> 31
lect6/swcantina-jedi.php Protected Pages session_start(); if (isset($_session['valid_user']) && ($_SESSION['user_type'] == 'jedi')) { echo "Jedi can see this.<br>"; else { echo "You must log in as a Jedi to see this page.<br>"; lect6/swcantina-jedimaster.php session_start(); if (isset($_session['valid_user']) && ($_SESSION['user_type'] == 'jedimaster')) { echo "Jedi Masters can see this.<br>"; else { echo "You must log in as a Jedi Master to see this page.<br>"; 32
Mid-term exam Mid-term is Feb. 26, Man 208, from 6:00-7:30pm 15% of overall course grade Closed book, close note, closed computer May bring one 8.5 x11 sheet of paper with notes Format Warm-up questions (multiple choice, definitions) Short answer questions Thinking questions Write / complete / correct code Understand and apply a concept Material covered All lectures, readings, assignments, and exercises up to and including Feb. 12 33