花了一天时间实现了一个 简单的用户登录验证的小模型。
基本实现了现在 用户登录模块的绝大多数功能, 也算是 熟悉了一下系统的逻辑。
在这个小模型中, 实现了以下的基本功能 :
- Logging in and authenticating users .
- Managing passwords
- Recording user preferences
- Personalizing content
- Recommending content based on existing knowledge about a user
简单来说,分为3个小模块组成 :
1. Register . 用户通过浏览 注册 成为 网站的 member
2. Login . 已经注册的用户通过 已注册的用户名和密码 登录网站, 显示用户的 个性化页面(Personalize Page)
3. Forget Password. 用户忘记密码,利用 phpMailer 通过 Gmail 往用户注册的邮箱发送一个随机生成的新密码。 用户可使用重新新密码登录。
这个 小Model 逻辑比较简单, 整个模型的 框架 如图 :
其中是利用了 phpMailer 通过 Gmail STMP 往注册用户发送邮件(因为localhost本身是没有注册STMP,
发出的邮件基本会被当做 垃圾邮件 处理)。这个模块的 代码没有放在 这里, 具体可以参考 下一篇。
/*** add_bm_form.php ***/
<?php /** * Created by IntelliJ IDEA. * User: Administrator * Date: 9/25/2015 * Time: 2:13 PM */ // Form for adding new bookmarks // include function files for this application require_once('bookmark_fns.php'); session_start(); // start output html do_html_header('Add Bookmarks'); check_valid_user(); display_add_bm_form(); display_user_menu(); do_html_footer(); ?>
/*** add_bms.php ***/
<?php /** * Created by IntelliJ IDEA. * User: Administrator * Date: 9/25/2015 * Time: 2:13 PM */ require_once('bookmark_fns.php'); session_start(); //create short variable name $new_url = $_POST['new_url']; do_html_header('Adding bookmarks'); try { check_valid_user(); if (!filled_out($_POST)) { throw new Exception('Form not completely filled out.'); } // check URL format if (strstr($new_url, 'http://')===false) $new_url = 'http://'.$new_url; // check URL is valid if (!(@fopen($new_url, 'r'))) throw new Exception('Not a valid URL.'); // try to add bm add_bm($new_url); echo 'Bookmark added.'; // get the bookmarks this user has saved if ($url_array = get_user_urls($_SESSION['valid_user'])) display_user_urls($url_array); } catch (Exception $e) { echo $e->getMessage(); } display_user_menu(); do_html_footer(); ?>
/*** bookmark_fns.php ***/
<?php /** * Created by IntelliJ IDEA. * User: Administrator * Date: 9/25/2015 * Time: 2:18 PM */ // A collection of includes for the application // we can include this file in all our files // this way, every file will contain all our functions and exceptions require_once('data_valid_fns.php'); require_once('db_fns.php'); require_once('user_auth_fns.php'); require_once('output_fns.php'); require_once('url_fns.php'); require_once('PHPMailer-master/examples/gmail.php'); ?>
/*** bookmark.sql ***/
# SQL stateemnts to create the PHPbookmark database CREATE database bookmarks; use bookmarks; CREATE TABLE user ( username VARCHAR(16) NOT NULL PRIMARY KEY , passwd CHAR(40) NOT NULL, email VARCHAR(100) NOT NULL ); CREATE TABLE bookmark ( username VARCHAR (16) NOT NULL , bm_URL VARCHAR(255) NOT NULL , index (username), index (bm_URL), PRIMARY KEY (username, bm_URL) ); GRANT SELECT , INSERT , UPDATE , DELETE ON bookmarks .* TO bm_user@localhost identified by 'password'; # set up this database on your system by running this set of commmands as the root MySQL suer. # You can do this with the following commond on your system's command line : # mysql -u root -p < bookmarks.sql
/*** change_passwd.php ***/
<?php /** * Created by IntelliJ IDEA. * User: Administrator * Date: 9/25/2015 * Time: 2:17 PM */ //script to change a user's password in the database require_once('bookmark_fns.php'); session_start(); do_html_header('Changing passwd'); //create short varible names $old_passwd = $_POST['old_passwd']; $new_passwd = $_POST['new_passwd']; $new_passwd2 = $_POST['new_passwd2']; try{ check_valid_user(); if(!filled_out($_POST)) { throw new Exception('You have not filled out the form completely. Please try again'); } if($new_passwd != $new_passwd2) { throw new Exception('Passwords entered were not the same. Not changed'); } // attempt update change_password change_password($_SESSION['valid_user'], $old_passwd, $new_passwd); echo 'Password changed'; } catch (Exception $e) { echo $e->getMessage(); } display_user_menu(); do_html_footer();
/*** change_passwd_form.php ***/
<?php /** * Created by IntelliJ IDEA. * User: Administrator * Date: 9/25/2015 * Time: 2:16 PM */ //Form for members to fill out if they want to change their passwords require_once('bookmark_fns.php'); session_start(); do_html_header('Change password'); check_valid_user(); display_password_form(); display_user_menu(); do_html_footer(); ?>
/*** data_valid_fns.php ***/
<?php /** * Created by IntelliJ IDEA. * User: Administrator * Date: 9/25/2015 * Time: 2:19 PM */ function filled_out( $form_vars ) { //test that each variable has a value foreach($form_vars as $key => $value) { if( (!isset($key)) || ($value=='') ) { return false; } } return true; } function valid_email($address) { // check an email address is possibly valid if (ereg('^[a-zA-Z0-9_\.\-]+@[a-zA-Z0-9\-]+\.[a-zA-Z0-9\-\.]+$', $address)) return true; else return false; }
/*** db_fns.php ***/
<?php /** * Created by IntelliJ IDEA. * User: Administrator * Date: 9/25/2015 * Time: 2:20 PM */ function db_connect() { $result = new mysqli('localhost', 'bm_user', 'password', 'bookmarks'); if(!$result) { throw new Exception('Could not connect to database server'); } else { return $result; } }
/*** delete_bms.php ***/
<?php /** * Created by IntelliJ IDEA. * User: Administrator * Date: 9/25/2015 * Time: 2:14 PM */ //Script to delete selected bookmarks from a user's list require_once('bookmark_fns.php'); session_start(); //create short varible names $del_me = $_POST['del_me']; $valid_user = $_SESSION['valid_user']; do_html_header('Deleting bookmarks'); check_valid_user(); if(!filled_out($_POST)) { echo '<p> You have not chosen any bookmarks to delete.<br> Please try again later .</p>'; display_user_menu(); do_html_footer(); exit; } else { if(count($del_me)>0 ) { foreach($del_me as $url) { if( delete_bm($valid_user, $url)) { echo 'Delete '.htmlspecialchars($url).'.<br />'; } else { echo 'Could not delete '.htmlspecialchars($url). '.<br />'; } } } else { echo 'No bookmarks selected for deletion'; } } // get the bookmarks this user has saved if( $url_array = get_user_urls($valid_user) ) { display_user_urls($url_array); } display_user_menu(); do_html_footer();
/*** forgot_form.php ***/
<?php /** * Created by IntelliJ IDEA. * User: Administrator * Date: 9/25/2015 * Time: 2:10 PM */ //Form for users to fill out if they've forgotten require_once('bookmark_fns.php'); do_html_header('Reset password'); display_forgot_form(); do_html_footer(); ?>
/*** forgot_passwd.php ***/
<?php /** * Created by IntelliJ IDEA. * User: Administrator * Date: 9/25/2015 * Time: 2:11 PM */ //Scritp to reset forgotten passwords require_once('bookmark_fns.php'); require_once('notify_passwd.php'); do_html_header("Resetting password"); //create short varible name $username = $_POST['username']; try{ $password = reset_password($username); notify_password($username, $password); echo 'Your new password has been emailed to you. <br />'; } catch (Exception $e) { echo 'Your password could not be reset - please try again later'; } do_html_URL('login.php', 'Login'); do_html_footer(); ?>
/*** login.php ***/
<?php /** * Created by IntelliJ IDEA. * User: Administrator * Date: 9/25/2015 * Time: 2:08 PM */ // Front page with login form for the system // require 'usr/file2.php'; // require 'usr/dict/file1.php'; require_once('bookmark_fns.php'); do_html_header(''); display_site_info(); display_login_form(); do_html_footer(); ?>
/*** logout.php ***/
<?php /** * Created by IntelliJ IDEA. * User: Administrator * Date: 9/25/2015 * Time: 2:17 PM */ //Script to log a user out of the application require_once('bookmark_fns.php'); session_start(); $old_user = $_SESSION['valid_user']; // store to test if they were logged in unset($_SESSION['valid_user']); $result_dest = session_destroy(); //start ouput html do_html_header('Logging Out'); if( !empty($old_user) ){ if($result_dest) { // if they were logged in and are now logged out echo 'Logged out.<br />'; do_html_URL('login.php','Login'); } else { //they were logged in and could not be logged out echo 'Could not log you out. <br />'; } } else { //if they were't logged in but came to this page somehow echo 'You were not logged in, and so have not been logged out.<br />'; do_html_URL('login.php','Login'); } do_html_footer(); ?>
/*** member.php ***/
<?php /** * Created by IntelliJ IDEA. * User: Administrator * Date: 9/25/2015 * Time: 2:12 PM */ // A user's main page, with a view of all his current bookmarks require_once('bookmark_fns.php'); session_start(); $username = $_POST['username']; $passwd = $_POST['passwd']; if($username && $passwd) { //they have just tried logging in try { login($username, $passwd); $_SESSION['valid_user'] = $username; } catch(Exception $e) { //unsuccessful login do_html_header('Problem:'); echo 'You could not be logged in. You must be logged in to view this page'; do_html_URL('login.php','Login'); do_html_footer(); exit; } } do_html_header('Home'); // This function checks that the current user has a registered session. // This is aimed at users who have not just logged in, but are mid-session check_valid_user(); // get the bookmarks this user has saved if($url_array = get_user_urls($_SESSION['valid_user'])) { display_user_urls($url_array); } // give menu of options display_user_menu(); do_html_footer();
/*** notify_passwd.php ***/
<?php /** * Created by IntelliJ IDEA. * User: Administrator * Date: 9/29/2015 * Time: 1:50 PM */ function notify_password($username, $password) { $conn = db_connect(); $select_query = "SELECT email FROM user WHERE username = '$username' "; $result = $conn->query($select_query); if(!$result) { throw new Exception('Could not find email address'); } else if ($result->num_rows == 0) { throw new Exception('Could not find email address'); } else { $row = $result->fetch_object(); $sendto_email = $row->email; $subject = "Please note that your password has changed"; $body = "Your PHPBookMark password has been changed to " .$password. "\r\n" ."Please change it next time you log in. \r\n"; $send_success = stmp_mail($sendto_email,$subject,$body,$username); if($send_success) { return true; } else { throw new Exception('Could not send email'); } } }
/*** output_fns.php ***/
<?php /** * Created by IntelliJ IDEA. * User: Administrator * Date: 9/25/2015 * Time: 2:21 PM */ function do_html_header($title) { // print an HTML header ?> <html> <head> <title><?php echo $title;?></title> <style> body { font-family: Arial, Helvetica, sans-serif; font-size: 13px } li, td { font-family: Arial, Helvetica, sans-serif; font-size: 13px } hr { color: #3333cc; width=300; text-align=left} a { color: #000000 } </style> </head> <body> <img src="bookmark.gif" alt="PHPbookmark logo" border=0 align=left valign=bottom height = 55 width = 57 /> <h1> PHPbookmark</h1> <hr /> <?php if($title) do_html_heading($title); } function do_html_footer() { // print an HTML footer ?> </body> </html> <?php } function do_html_heading($heading) { // print heading ?> <h2><?php echo $heading;?></h2> <?php } function do_html_URL($url, $name) { // output URL as link and br ?> <br /><a href="<?php echo $url;?>"><?php echo $name;?></a><br /> <?php } function display_site_info() { // display some marketing info ?> <ul> <li>Store your bookmarks online with us!</li> <li>See what other users use!</li> <li>Share your favorite links with others!</li> </ul> <?php } function display_login_form() { ?> <a href='register_form.php'>Not a member?</a> <form method='post' action='member.php'> <table bgcolor='#cccccc'> <tr> <td colspan=2>Members log in here:</td> <tr> <td>Username:</td> <td><input type='text' name='username'></td></tr> <tr> <td>Password:</td> <td><input type='password' name='passwd'></td></tr> <tr> <td colspan=2 align='center'> <input type='submit' value='Log in'></td></tr> <tr> <td colspan=2><a href='forgot_form.php'>Forgot your password?</a></td> </tr> </table></form> <?php } function display_registration_form() { ?> <form method='post' action='register_new.php'> <table bgcolor='#cccccc'> <tr> <td>Email address:</td> <td><input type='text' name='email' size=30 maxlength=100></td></tr> <tr> <td>Preferred username <br />(max 16 chars):</td> <td valign='top'><input type='text' name='username' size=16 maxlength=16></td></tr> <tr> <td>Password <br />(between 6 and 16 chars):</td> <td valign='top'><input type='password' name='passwd' size=16 maxlength=16></td></tr> <tr> <td>Confirm password:</td> <td><input type='password' name='passwd2' size=16 maxlength=16></td></tr> <tr> <td colspan=2 align='center'> <input type='submit' value='Register'></td></tr> </table></form> <?php } function display_user_urls($url_array) { // display the table of URLs // set global variable, so we can test later if this is on the page global $bm_table; $bm_table = true; ?> <br /> <form name='bm_table' action='delete_bms.php' method='post'> <table width=300 cellpadding=2 cellspacing=0> <?php $color = "#cccccc"; echo "<tr bgcolor='$color'><td><strong>Bookmark</strong></td>"; echo "<td><strong>Delete?</strong></td></tr>"; if (is_array($url_array) && count($url_array)>0) { foreach ($url_array as $url) { if ($color == "#cccccc") $color = "#ffffff"; else $color = "#cccccc"; // remember to call htmlspecialchars() when we are displaying user data echo "<tr bgcolor='$color'><td><a href=\"$url\">".htmlspecialchars($url)."</a></td>"; echo "<td><input type='checkbox' name=\"del_me[]\" value=\"$url\"></td>"; echo "</tr>"; } } else echo "<tr><td>No bookmarks on record</td></tr>"; ?> </table> </form> <?php } function display_user_menu() { // display the menu options on this page ?> <hr /> <a href="member.php">Home</a> | <a href="add_bm_form.php">Add BM</a> | <?php // only offer the delete option if bookmark table is on this page global $bm_table; if($bm_table==true) echo "<a href='#' onClick='bm_table.submit();'>Delete BM</a> | "; else echo "<font color='#cccccc'>Delete BM</font> | "; ?> <a href="change_passwd_form.php">Change password</a> <br /> <a href="recommend.php">Recommend URLs to me</a> | <a href="logout.php">Logout</a> <hr /> <?php } function display_add_bm_form() { // display the form for people to ener a new bookmark in ?> <form name='bm_table' action='add_bms.php' method='post'> <table width=250 cellpadding=2 cellspacing=0 bgcolor='#cccccc'> <tr><td>New BM:</td><td><input type='text' name='new_url' value="http://" size=30 maxlength=255></td></tr> <tr><td colspan=2 align='center'><input type='submit' value='Add bookmark'></td></tr> </table> </form> <?php } function display_password_form() { // display html change password form ?> <br /> <form action='change_passwd.php' method='post'> <table width=250 cellpadding=2 cellspacing=0 bgcolor='#cccccc'> <tr><td>Old password:</td> <td><input type='password' name='old_passwd' size=16 maxlength=16></td> </tr> <tr><td>New password:</td> <td><input type='password' name='new_passwd' size=16 maxlength=16></td> </tr> <tr><td>Repeat new password:</td> <td><input type='password' name='new_passwd2' size=16 maxlength=16></td> </tr> <tr><td colspan=2 align='center'><input type='submit' value='Change password'> </td></tr> </table> <br /> <?php }; function display_forgot_form() { // display HTML form to reset and email password ?> <br /> <form action='forgot_passwd.php' method='post'> <table width=250 cellpadding=2 cellspacing=0 bgcolor='#cccccc'> <tr><td>Enter your username</td> <td><input type='text' name='username' size=16 maxlength=16></td> </tr> <tr><td colspan=2 align='center'><input type='submit' value='Change password'> </td></tr> </table> <br /> <?php }; function display_recommended_urls($url_array) { // similar output to display_user_urls // instead of displaying the users bookmarks, display recomendation ?> <br /> <table width=300 cellpadding=2 cellspacing=0> <?php $color = "#cccccc"; echo "<tr bgcolor=$color><td><strong>Recommendations</strong></td></tr>"; if (is_array($url_array) && count($url_array)>0) { foreach ($url_array as $url) { if ($color == "#cccccc") $color = "#ffffff"; else $color = "#cccccc"; echo "<tr bgcolor='$color'><td><a href=\"$url\">".htmlspecialchars($url)."</a></td></tr>"; } } else echo "<tr><td>No recommendations for you today.</td></tr>"; ?> </table> <?php }; ?>
/*** recommend.php ***/
<?php /** * Created by IntelliJ IDEA. * User: Administrator * Date: 9/25/2015 * Time: 2:15 PM */ //Script to suggest recommendations to a user, based on users with similar interests
/*** register_form.php ***/
<?php /** * Created by IntelliJ IDEA. * User: Administrator * Date: 9/25/2015 * Time: 2:08 PM */ //Form for users to register in the system require_once('bookmark_fns.php'); do_html_header('User registration'); display_registration_form(); do_html_footer(); ?>
/*** register_new.php ***/
<?php /** * Created by IntelliJ IDEA. * User: Administrator * Date: 9/25/2015 * Time: 2:10 PM */ require_once('bookmark_fns.php'); //Script to process new registrations $email = $_POST['email']; $username = $_POST['username']; $passwd = $_POST['passwd']; $passwd2 = $_POST['passwd2']; // start session which may be needed later // start it now becuase it must go before headers session_start(); try { //check forms filled in if(!filled_out($_POST)) { throw new Exception('You have not filled the form out correctly - Please go back and try again'); } // email address not valid if(!valid_email($email)) { throw new Exception('That is not a valid email address - Please go back and try again'); } // passwords not the same if( $passwd != $passwd2) { throw new Exception('The passwords you enteren do not match - Please go back and try again'); } // check password length is ok // ok if username truncates, but passwords will get // munged if they are too long if((strlen($passwd) < 6) || (strlen($passwd) > 16)) { throw new Exception('Your password must be between 6 and 16 characters - Please go back and try again'); } // attempt to register // this function can also throw an exception register($username, $email, $passwd) ; // register session variable $_SESSION['valid_user'] = $username; //provide link to members page do_html_header("Registration successful"); echo 'Your registration was successful. Go to the memers page to start setting up your bookmarks!'; do_html_URL('member.php', 'Go to members page'); //end page } catch (Exception $e) { do_html_header('Problem:'); echo $e->getMessage(); do_html_footer(); exit; }
/*** url_fns.php ***/
<?php /** * Created by IntelliJ IDEA. * User: Administrator * Date: 9/25/2015 * Time: 2:20 PM */ require_once('db_fns.php'); function add_bm($new_url) { // Add new bookmark to the database echo "Attempting to add ".htmlspecialchars($new_url).'<br />'; $valid_user = $_SESSION['valid_user']; $conn = db_connect(); // check not a repeat bookmark $result = $conn->query("select * from bookmark where username='$valid_user' and bm_URL='$new_url'"); if ($result && ($result->num_rows>0)) throw new Exception('Bookmark already exists.'); // insert the new bookmark if (!$conn->query( "insert into bookmark values ('$valid_user', '$new_url')")) throw new Exception('Bookmark could not be inserted.'); return true; } function get_user_urls($username) { //extract from the database all the URLs this user has stored $conn = db_connect(); $result = $conn->query( "select bm_URL from bookmark where username = '$username'"); if (!$result) return false; //create an array of the URLs $url_array = array(); for ($count = 1; $row = $result->fetch_row(); ++$count) { $url_array[$count] = $row[0]; } return $url_array; } function delete_bm($user, $url) { // delete one URL from the database $conn = db_connect(); // delete the bookmark if (!$conn->query( "delete from bookmark where username='$user' and bm_url='$url'")) throw new Exception('Bookmark could not be deleted'); return true; }
/*** user_auth_fns.php ***/
<?php /** * Created by IntelliJ IDEA. * User: Administrator * Date: 9/25/2015 * Time: 2:20 PM */ function register($username, $email, $password) { //register new person with db //return true or error message // connect to db $conn = db_connect(); //check if username is unique $check_query = "SELECT * FROM user WHERE username= '$username' "; $result = mysqli_query($conn, $check_query); if( !$result ) { throw new Exception('Could not excute the check query'); } if( $result->num_rows>0 ) { throw new Exception('That username is taken - Go back and choose another one'); } // if ok, put in db $insert_query = "INSERT INTO user VALUE ('$username', sha1('$password'), '$email')"; $result = $conn->query($insert_query); if(!$insert_query) { throw new Exception('Could not register you in database - Please try again later.'); } return true; } //This function checks a User's Details Against the Database function login($username, $password) { //check username and password with db //if yes, return true //else throw exception $conn = db_connect(); $check_query = "SELECT * FROM user WHERE username = '$username' AND passwd = sha1('$password')" ; $result = $conn->query($check_query); if(!result) { throw new Exception('Could not log you in'); } if($result->num_rows > 0) { return true; } else { throw new Exception('Could not log you in'); } } // This function Checks That the User Has a Valid Session function check_valid_user() { //see if somebody is logged in and notify them if not if( isset($_SESSION['valid_user']) ) { echo "Logged in as " .$_SESSION['valid_user'] .".</br>"; } else { // they are not logged in do_html_heading('Problem:'); echo 'You are not logged in .</br>'; do_html_URL('login.php', 'Login'); do_html_footer(); exit; } } //This function Updates a User Password in the DataBase function change_password($username, $old_password, $new_password) { // change password for username / old_password to new_password // if the old password is right // change their password to new_password and return true // else throw an exception login($username, $old_password); $conn = db_connect(); $update_query = "UPDATE user SET passwd = sha1('$new_password') WHERE username = '$username'"; $result = $conn->query($update_query); if( !$result ) { throw new Exception('Password could not be changed'); } else { return true; } } function get_random_word($min_length, $max_length) // grab a random word from dictionary between the two lengths // and return it { // generate a random word $word = ''; // remember to change this path to suit your system $dictionary = '\usr\dict\words'; // the ispell dictionary $fp = @fopen($dictionary, 'r'); if(!$fp) return false; $size = filesize($dictionary); // go to a random location in dictionary srand ((double) microtime() * 1000000); $rand_location = rand(0, $size); fseek($fp, $rand_location); // get the next whole word of the right length in the file while (strlen($word)< $min_length || strlen($word)>$max_length || strstr($word, "'")) { if (feof($fp)) fseek($fp, 0); // if at end, go to start $word = fgets($fp, 80); // skip first word as it could be partial $word = fgets($fp, 80); // the potential password }; $word=trim($word); // trim the trailing \n from fgets return $word; } //This function Resets a User's Password to a Random Value and Emails Her the New One function reset_password($username) // set password for username to a random value // return the new password or false on failure { // get a random dictionary word b/w 6 and 13 chars in length $new_password = get_random_word(6, 13); if($new_password==false) throw new Exception('Could not generate new password.'); // add a number between 0 and 999 to it // to make it a slightly better password srand ((double) microtime() * 1000000); $rand_number = rand(0, 999); $new_password .= $rand_number; // set user's password to this in database or return false $conn = db_connect(); $result = $conn->query( "update user set passwd = sha1('$new_password') where username = '$username'"); if (!$result) throw new Exception('Could not change password.'); // not changed else return $new_password; // changed successfully }