Tạo mạng xã hội với PHP - part 10 docx

10 278 0
Tạo mạng xã hội với PHP - part 10 docx

Đang tải... (xem toàn văn)

Thông tin tài liệu

Users, Registration, and Authentication [ 72 ] } // password length if( strlen( $_POST['register_password'] ) < 6 ) { $allClear = false; $this->registrationErrors[] = 'Your password is too short, it must be at least 6 characters'; $this->registrationErrorLabels['register_password_label'] = 'error'; $this->registrationErrorLabels['register_password_confirm_ label'] = 'error'; } Next, we have the e-mail address—we need to check it for header injection, and that the format of the e-mail address is correct. The rst highlighted section of code shows the header injection check, and the second shows the format check. // email headers if( strpos( ( urldecode( $_POST[ 'register_email' ] ) ), "\r" ) === true || strpos( ( urldecode( $_POST[ 'register_email' ] ) ), "\n" ) === true ) { $allClear = false; $this->registrationErrors[] = 'Your email address is not valid (security)'; $this->registrationErrorLabels['register_email_label'] = 'error'; } // email valid if( ! preg_match( "^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a- z0-9-]+)*(\.[a-z]{2,4})^", $_POST[ 'register_email' ] ) ) { $allClear = false; $this->registrationErrors[] = 'You must enter a valid email address'; $this->registrationErrorLabels['register_email_label'] = 'error'; } To help protect us from a legal perspective, we should get legal advice on the policies and terms and conditions we need to enforce on our social network. When we have such terms in place, we will want our users to accept these before allowing them to join—let's ensure they ticked the appropriate box on our registration form template: This material is copyright and is licensed for the sole use by RAYMOND ERAZO on 25th October 2010 3146 KERNAN LAKE CIRCLE, JACKSONVILLE, 32246 Download from www.eBookTM.com Chapter 3 [ 73 ] // terms accepted if( ! isset( $_POST['register_terms'] ) || $_POST['register_ terms'] != 1 ) { $allClear = false; $this->registrationErrors[] = 'You must accept our terms and conditions.'; $this->registrationErrorLabels['register_terms_label'] = 'error'; } If a user signs up with the e-mail address or username of an existing user, we will have some problems—particularly when they come to log in, or request an e-mail to reset their password. To prevent this, we need to check that the username and e-mail address are not currently in use by another user, which can be done with a simple database query: // duplicate user+email check $u = $this->registry->getObject('db')->sanitizeData( $_ POST['register_user'] ); $e = $this->registry->getObject('db')->sanitizeData( $_ POST['register_email'] ); $sql = "SELECT * FROM users WHERE username='{$u}' OR email='{$e}'"; $this->registry->getObject('db')->executeQuery( $sql ); if( $this->registry->getObject('db')->numRows() == 2 ) { $allClear = false; // both $this->registrationErrors[] = 'Both your username and email address are already in use on this site.'; $this->registrationErrorLabels['register_user_label'] = 'error'; $this->registrationErrorLabels['register_email_label'] = 'error'; } elseif( $this->registry->getObject('db')->numRows() == 1 ) { // possibly both, or just one $u = $this->registry->getObject('db')->sanitizeData( $_ POST['register_user'] ); $e = $this->registry->getObject('db')->sanitizeData( $_ POST['register_email'] ); $data = $this->registry->getObject('db')->getRows(); if( $data['username'] == $u && $data['email'] == $e ) { This material is copyright and is licensed for the sole use by RAYMOND ERAZO on 25th October 2010 3146 KERNAN LAKE CIRCLE, JACKSONVILLE, 32246 Download from www.eBookTM.com Users, Registration, and Authentication [ 74 ] $allClear = false; $this->registrationErrors[] = 'Both your username and password are already in use on this site.'; $this->registrationErrorLabels['register_user_label'] = 'error'; $this->registrationErrorLabels['register_email_label'] = 'error'; // both } elseif( $data['username'] == $u ) { $allClear = false; // username $this->registrationErrors[] = 'Your username is already in use on this site.'; $this->registrationErrorLabels['register_user_label'] = 'error'; } else { $allClear = false; // email address $this->registrationErrors[] = 'Your email address is already in use on this site.'; $this->registrationErrorLabels['register_email_label'] = 'error'; } } Finally, before we go onto prole elds, we check to see if we have enabled CAPTCHA. If we have, then we should do a check that the user is a human and not an automated spam bot. We will discuss CAPTCHA implementation later in this chapter. // captcha if( $this->registry->getSetting('captcha.enabled') == 1 ) { // captcha check } This material is copyright and is licensed for the sole use by RAYMOND ERAZO on 25th October 2010 3146 KERNAN LAKE CIRCLE, JACKSONVILLE, 32246 Download from www.eBookTM.com Chapter 3 [ 75 ] Now that we have checked all of the core elds, we pass control to our registration extension, which will process all of the prole related elds: // hook if( $this->registrationExtention->checkRegistrationSubmission() == false ) { $allClear = false; } If all is clear (that is, there were no errors either from this function, or the registration controller extension), then we store our sanitized data, and return true—so that another method can create the user account and prole: if( $allClear == true ) { $this->sanitizedValues['username'] = $u; $this->sanitizedValues['email'] = $e; $this->sanitizedValues['password_hash'] = md5( $_ POST['register_password'] ); $this->sanitizedValues['active'] = $this->activeValue; $this->sanitizedValues['admin'] = 0; $this->sanitizedValues['banned'] = 0; $this->submittedValues['register_user'] = $_POST['register_ user']; $this->submittedValues['register_password'] = $_ POST['register_password']; return true; } else { $this->submittedValues['register_user'] = $_POST['register_ user']; $this->submittedValues['register_email'] = $_POST['register_ email']; $this->submittedValues['register_password'] = $_ POST['register_password'] ; $this->submittedValues['register_password_confirm'] = $_ POST['register_password_confirm'] ; $this->submittedValues['register_captcha'] = ( isset( $_ POST['register_captcha'] ) ? $_POST['register_captcha'] : '' ); return false; } } This material is copyright and is licensed for the sole use by RAYMOND ERAZO on 25th October 2010 3146 KERNAN LAKE CIRCLE, JACKSONVILLE, 32246 Download from www.eBookTM.com Users, Registration, and Authentication [ 76 ] Hooking additional elds on Depending on the social network we were developing, we will have different prole elds. To make our code exible, these elds are abstracted to a registration extension, so if we reuse our code, we simply need to change this one le to process these additional elds, and we know that it won't interfere with our core elds. In Dino Space land, citizens are only permitted to keep one Dinosaur, after all, who could cope with looking after more than one! This would need to be tweaked slightly if we wanted to extend our registration form to accept any number of a particular set of elds. There is some JavaScript available to help with such a situation (http://www.michaelpeacock.co.uk/blog/entry/add-another-item-with- php-and-jquery and http://www.michaelpeacock.co.uk/blog/entry/add- another-the-jquery-plugin should get you started if you want to try it). For Dino Space, there are going to be certain prole elds we want, and some examples include: • Dinosaur's name • Dinosaur's breed • Dinosaur's gender • Dinosaur's date of birth The registry extension works in a similar way to the core registration controller, except the data validation is more dynamic, based on how the additional prole elds are dened. For example, to create the four additional prole elds from above, we would dene the following: private $registry; private $extraFields = array(); private $errors = array(); private $submittedValues = array(); private $sanitizedValues = array(); private $errorLabels = array(); public function __construct( $registry ) { $this->registry = $registry; $this->extraFields['dino_name'] = array( 'friendlyname' => 'Pet Dinosaurs Name', 'table' => 'profile', 'field' => 'dino_name', 'type' => 'text', 'required' => false ); $this->extraFields['dino_breed'] = array( 'friendlyname' => 'Pet Dinosaurs Breed', 'table' => 'profile', 'field' => 'dino_breed', 'type' => 'text', 'required' => false ); $this->extraFields['dino_gender'] = array( 'friendlyname' => This material is copyright and is licensed for the sole use by RAYMOND ERAZO on 25th October 2010 3146 KERNAN LAKE CIRCLE, JACKSONVILLE, 32246 Download from www.eBookTM.com Chapter 3 [ 77 ] 'Pet Dnosaurs Gender', 'table' => 'profile', 'field' => 'dino_gender', 'type' => 'list', 'required' => false, 'options' => array( 'male', 'female') ); $this->extraFields['dino_dob'] = array( 'friendlyname' => 'Pet Dinosaurs Date of Birth', 'table' => 'profile', 'field' => 'dino_dob', 'type' => 'DOB', 'required' => false ); } Let's take a look at why we structure our extraFields like this. To do this, we need to look at how the extension validates the registration submission. public function checkRegistrationSubmission() { We set a $valid variable (just like our allClear variable in the registration controller). If there are errors, we set this to false. $valid = true; We now iterate through the elds to process them individually: foreach( $this->extraFields as $field => $data ) { Firstly, we check to see whether the eld is required (from the required element of the data array). If it is, we check that the user has submitted a value. If they haven't, we store the necessary errors. if( ( ! isset( $_POST['register_' . $field] ) || $_POST['register_' . $field] == '' ) && $data['required'] = true ) { $this->submittedValues[ $field ] = $_POST['register_' . $field]; $this->errorLabels['register_' . $field .'_label'] = 'error'; $this->errors[] = 'Field ' . $data['friendlyname'] . ' cannot be blank'; $valid = false; } If the eld isn't required, and hasn't been set, then we note that, and move on. elseif( $_POST['register_' . $field] == '' ) { $this->submittedValues[ 'register_' . $field ] = ''; } else { This material is copyright and is licensed for the sole use by RAYMOND ERAZO on 25th October 2010 3146 KERNAN LAKE CIRCLE, JACKSONVILLE, 32246 Download from www.eBookTM.com Users, Registration, and Authentication [ 78 ] If our eld is set, we then validate it depending on the type of data we are expecting. By default, there are three options: • Text—text inputs • Int—integers • List—list of predened options However, it has been designed to allow other types to be plugged in, for instance, dates. The type also dictates how the data should be sanitized. if( $data['type'] == 'text' ) { $this->sanitizedValues[ 'register_' . $field ] = $this- >registry->getObject('db')->sanitizeData( $_ POST['register_' . $field] ); $this->submittedValues['register_' . $field] = $_ POST['register_' . $field]; } elseif( $data['type'] == 'int' ) { $this->sanitizedValues[ 'register_' . $field ] = intval( $_POST['register_' . $field] ); $this->submittedValues['register_' . $field] = $_ POST['register_' . $field]; } elseif( $data['type'] == 'list' ) { If the data type is a list, we simply check to see whether the value is in the array of options, if it isn't we have an error, if it is—everything is OK. if( ! in_array( $_POST['register_' . $field], $data['options'] ) ) { $this->submittedValues[ $field ] = $_ POST['register_' . $field]; $this->errorLabels['register_' . $field .'_label'] = 'error'; $this->errors[] = 'Field ' . $data['friendlyname'] . ' was not valid'; $valid = false; } else { $this->sanitizedValues[ 'register_' . $field ] = intval( $_POST['register_' . $field] ); $this->submittedValues['register_' . $field] = $_ POST['register_' . $field]; This material is copyright and is licensed for the sole use by RAYMOND ERAZO on 25th October 2010 3146 KERNAN LAKE CIRCLE, JACKSONVILLE, 32246 Download from www.eBookTM.com Chapter 3 [ 79 ] } } else { Finally, for non-standard cases, we call a custom method, which we would create for each such type: $method = 'validate_' . $data['type']; if( $this->$method( $_POST['register_' . $field] ) == true ) { $this->sanitizedValues[ 'register_' . $field ] = $this->registry->getObject('db')->sanitizeData( $_POST['register_' . $field] ); $this->submittedValues['register_' . $field] = $_ POST['register_' . $field]; } else { $this->sanitizedValues[ 'register_' . $field ] = $this->registry->getObject('db')->sanitizeData( $_POST['register_' . $field] ); $this->submittedValues['register_' . $field] = $_ POST['register_' . $field]; $this->errors[] = 'Field ' . $data['friendlyname'] . ' was not valid'; $valid = false; } } } } Once all the processing has been done, and sanitized data has been stored, we simply return whether there were errors or not: if( $valid == true ) { return true; } else { return false; } } This material is copyright and is licensed for the sole use by RAYMOND ERAZO on 25th October 2010 3146 KERNAN LAKE CIRCLE, JACKSONVILLE, 32246 Download from www.eBookTM.com Users, Registration, and Authentication [ 80 ] Processing the registration Once we have processed all of the elds submitted and checked that they are all valid, we are then ready to create our user account and our prole. Creating the user is a simple case of inserting the serialized values into the users table. Then, we pass control to the extension so that it can process the prole elds. /** * Process the users registration, and create the user and users profiles * @return int */ private function processRegistration() { // insert $this->registry->getObject('db')->insertRecords( 'users', $this->sanitizedValues ); // get ID $uid = $this->registry->getObject('db')->lastInsertID(); // call extension to insert the profile $this->registrationExtention->processRegistration( $uid ); // return the ID for the frameworks reference - autologin? return $uid; } Creating the prole Within our extra elds array, we noted the table and eld that the submitted value should be inserted into. This method goes through the array, and groups the values for each table, to ensure that only one insert is performed per additional table. The advantage of this means if we added elds for another table (perhaps subscription information for paid user accounts), we can do this without needing to add more functionality to our extension. /** * Create our user profile * @param int $uid the user ID * @return bool */ public function processRegistration( $uid ) { $tables = array(); $tableData = array(); This material is copyright and is licensed for the sole use by RAYMOND ERAZO on 25th October 2010 3146 KERNAN LAKE CIRCLE, JACKSONVILLE, 32246 Download from www.eBookTM.com Chapter 3 [ 81 ] // group our profile fields by table, so we only need to do one insert per table foreach( $this->extraFields as $field => $data ) { if( ! ( in_array( $data['table'], $tables ) ) ) { $tables[] = $data['table']; $tableData[ $data['table'] ] = array( 'user_id' => $uid, $data['field'] => $this->sanitizedValues[ 'register_' . $field ]); } else { $tableData[ $data['table'] ] = array( 'user_id' => $uid, $data['field'] => $this->sanitizedValues[ 'register_' . $field ]); } } foreach( $tableData as $table => $data ) { $this->registry->getObject('db')->insertRecords( $table, $data ); } return true; } Putting it all together: registration constructor So, we have gone through our registration controller, and our registration controller extension to see how they process data to create our user account and user prole. We now just need to bring this all together in the constructor. Firstly, we assign our registry object: $this->registry = $registry; Next, we include the extension le, and create the object: require_once FRAMEWORK_PATH . 'controllers/authenticate/ registrationcontrollerextention.php'; $this->registrationExtention = new Registrationcontrollerextention( $this->registry ); We then check to see if the user has tried to submit the registration form: if( isset( $_POST['process_registration'] ) ) { This material is copyright and is licensed for the sole use by RAYMOND ERAZO on 25th October 2010 3146 KERNAN LAKE CIRCLE, JACKSONVILLE, 32246 Download from www.eBookTM.com . ! preg_match( "^[_a-z 0-9 -] +(.[_a-z 0-9 -] +)*@[a-z 0-9 -] +(.[a- z 0-9 -] +)*(.[a-z]{2,4})^", $_POST[ 'register_email' ] ) ) { $allClear = false; $this->registrationErrors[]. number of a particular set of elds. There is some JavaScript available to help with such a situation (http://www.michaelpeacock.co.uk/blog/entry/add-another-item-with- php- and-jquery and. $this->registry->getObject('db' )-& gt;executeQuery( $sql ); if( $this->registry->getObject('db' )-& gt;numRows() == 2 ) { $allClear = false; // both $this->registrationErrors[]

Ngày đăng: 04/07/2014, 21:20

Tài liệu cùng người dùng

Tài liệu liên quan