Agile Web Application Development with Yii 1.1 and PHP5 phần 6 potx

36 459 0
Agile Web Application Development with Yii 1.1 and PHP5 phần 6 potx

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

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

Chapter 7 [ 167 ] states. These are the extra user values that should be persisted throughout a user's session. As an example of this, we are setting the attribute named lastLoginTime to be the value of the last_login_time eld in the database. This way, at any place in the application, this attribute can be accessed via: Yii::app()->user->lastLoginTime; As the initial user rows go into the table with null values for the last login time, there is a quick check for null so that we can store an appropriate time when the user logs in for the very rst time. We have also taken the time to format the date for better readability. The reason we take a different approach when storing the last login time versus the ID is that id just happens to be an explicitly dened property on the CUserIdentity class. So, other than name and id, all other user attributes that need to be persisted throughout the session can be set in a similar manner. When cookie-based authentication is enabled (by setting CWebUser::allowAutoLogin to be true), these user identity states will be stored in cookie. Therefore, you should not store sensitive information (for example, password) in the same manner as we have stored the user's last login time. With these changes in place, you will now need to provide a correct username and password combination for a user dened in the tbl_user table in the database. Using demo/demo or admin/admin will, of course, no longer work. Give it a try. You should be able to log in as any one of the users you created earlier in this chapter. If you followed along and have the same user data as we do, the following credentials should work: Username: Test_User_One Password: test1 Now that we have altered the login process to authenticate against the database, we won't be able to access the delete functionality for any of our project, issue or user entities. The reason for this is that there are authorization checks in place to ensure that the user is an admin prior to allowing access. Currently, none of our database users have been congured to be admins. Don't worry, authorization is the focus of the next iteration, so we will be able to access that functionality again soon. Iteration 4: User Management and Authentication [ 168 ] Updating the user last login time As we mentioned earlier in this chapter, we removed the last login time as an input eld on the user creation form, but we still need to add the logic to properly update this eld. As we are tracking the last login time in the tbl_user database table, we need to update this eld accordingly after a successful login. As the actual login happens in the LoginForm::login() method in the form model class, let's update this value there. Add the following highlighted line to the LoginForm::login() method: /** * Logs in the user using the given username and password in the model. * @return boolean whether login is successful */ public function login() { if($this->_identity===null) { $this->_identity=new UserIdentity($this->username,$this- >password); $this->_identity->authenticate(); } if($this->_identity->errorCode===UserIdentity::ERROR_NONE) { $duration=$this->rememberMe ? 3600*24*30 : 0; // 30 days Yii::app()->user->login($this->_identity,$duration); User::model()->updateByPk($this->_identity->id, array('last_ login_time'=>new CDbExpression('NOW()'))); return true; } else return false; } Here we are calling its updateByPk() method as an efcient approach to simply update the User record, specifying the Primary Key as well as an array of name=>value pairs for the columns we want to update. Chapter 7 [ 169 ] Displaying the last login time on the home page Now that we are updating the last login time in the db, and saving it to persistent session storage when logging in, let's go ahead and display this time on our welcome screen that a user sees after a successful login. This will also help make us feel better because we know that all of this is working as expected. Open up the default view le that is responsible for displaying our homepage: protected/views/site/index.php. Add the following highlighted lines of code just below the welcome statement: <h1>Welcome to <i><?php echo CHtml::encode(Yii::app()->name); ?></i></ h1> <?php if(!Yii::app()->user->isGuest):?> <p> You last logged in on <?php echo date( 'l, F d, Y, g:i a', Yii::app()->user->lastLoginTime ); ?>. </p> <?php endif;?> And as we are in there, let's go ahead and remove all of the other autogenerated help text, which is everything below these lines we just added. Once you save your changes and log in again, you should see something similar to the screenshot below, which displays the welcome message following by a formatted time indicating your last successful login: Iteration 4: User Management and Authentication [ 170 ] Summary This iteration was the rst of two iterations focused on user management, authentication and authorization. We created the ability to manage CRUD operations for application users, making many adjustments to the new user creation process along the way. We added a new base class for all of our Active Record classes, so that we can easily manage our audit history table columns that are present on all of our tables. We also updated our code to properly manage the user's last login time, which we are storing in the database. In doing so, we learned about tapping into the CActiveRecord validation workow to allow for pre and post-validation processing. We then focused on understanding the Yii authentication model in order to enhance it to meet our application's requirements: that the user credentials be validated against the values stored in the database. Now that we have covered authentication, we can turn focus to second part of Yii's auth-and-auth framework, authorization. This will be the focus of the next iteration. Iteration 5: User Access Control User based web applications, like our TrackStar application, typically need to control access to certain functionality based on who is making the request. When we speak of user access control, we are referring, at a high-level, to some questions the application needs to ask when requests are being made such as: • Who is making the request? • Does that user have the appropriate permission to access the requested functionality? The answers to these questions help the application respond appropriately. The work completed in the last iteration provides the application with the ability to answer the rst question. Our implementation of basic user management extended the application user authentication process to use the database. The application now allows users to establish their own authentication credentials and validates the username and password against the database stored values upon user login. After a successful login, the application now knows exactly who is making subsequent requests. This iteration is going to focus on helping the application answer the second question. Once the user has provided appropriate identication, the application needs a way to determine if they also have the permission to perform the requested action. We'll extend our basic authorization model by taking advantage of Yii's user access control features. Yii provides both a simple access control lter as well as a more sophisticated role-based access control (RBAC) implementation as means to help us address our user authorization requirements. We'll be taking a closer look at both of these as we work to implement the user access requirements for the TrackStar application. Iteration 5: User Access Control [ 172 ] Iteration planning When we rst introduced our TrackStar application back in Chapter 3, The TrackStar Application, we mentioned that the application has two high-level user types: anonymous and authenticated. This is simply making a distinction between a user that has successfully logged in, and one who has not. We have also introduced the idea of authenticated users having different roles within a project. We established that, within a project, a user can be in one of three roles: • A project owner (is granted all administrative access to the project) • A project member (is granted more limited access to project features and functionality) • A project reader (only has access to read the content associated with a project, not change it in any way) The focus of this iteration is to implement an approach to managing the access control granted to application users. We need a way to create and manage our roles and permissions, assign them to users, and enforce the access control rules we want for each user role. In order to achieve this goal, we need to identify all the more granular items we will work on within this iteration. The following is a list of these items: • Implement a strategy to force the user to log in before gaining access to any project or issue related functionality • Create user roles and associate those roles with a specic functionality permission structure • Implement the ability to assign users to roles (and their associated permissions) • Ensure our role and permission structure exists on a per project basis (that is, allow users to have different permissions within different projects) • Implement the ability to associate users to projects and, at the same time, to roles within that project • Implement the necessary authorization access checking throughout the application to appropriately grant or deny access to the application user based on their permissions Luckily, Yii comes with a lot of built-in functionality to help us implement these requirements. So, let's get started. Chapter 8 [ 173 ] Running our existing test suite As always, we should kick things off by running all of our existing unit tests to ensure that the tests pass: % cd WebRoot/protected/tests/ % phpunit unit/ PHPUnit 3.4.12 by Sebastian Bergmann. Time: 3 seconds OK (10 tests, 27 assertions) Everything looks good, so we can start making changes. accessControl lter We introduced lters back in Chapter 6, Iteration 3: Adding Tasks when we added one to help us verify the project context when dealing with our Issue related CRUD operations. The Yii Framework provides a lter called accessControl. This lter can be directly used in controller classes to provide an authorization scheme to verify whether or not a user can access a specic controller action. In fact, the astute reader will remember that when we were implementing our filterProjectContext lter back in Chapter 6, we noticed that access control lter was already included in the lters list for both our IssueController and ProjectController classes, as follows: /** * @return array action filters */ public function filters() { return array( 'accessControl', // perform access control for CRUD operations ); } This was included in the autogenerated code produced by using the Gii code generator to create our skeleton CRUD operations on the Issue and Project AR classes. Iteration 5: User Access Control [ 174 ] The default implementation is set up to allow anyone to view a list of existing issues and projects. However, it restricts access of creating and updating to authenticated users, and further restricts the Delete action to a special admin user. You might remember that when we rst implemented CRUD operations on projects, we had to log in before we were able to create new ones. The same was true when dealing with issues and again with users. The mechanism controlling this authorization and access is exactly this accessControl lter. Let's take a closer look at this implementation within the ProjectController.php class le. There are two methods relevant to access control in this le, ProjectController::filters() and ProjectController::accessRules(). The code for the rst method is listed as follows: /** * @return array action filters */ public function filters() { return array( 'accessControl', // perform access control for CRUD operations ); } The following code is used for the second method: /** * Specifies the access control rules. * This method is used by the 'accessControl' filter. * @return array access control rules */ public function accessRules() { return array( array('allow', // allow all users to perform 'index' and 'view' actions 'actions'=>array('index','view'), 'users'=>array('*'), ), array('allow', // allow authenticated user to perform 'create' and 'update' actions 'actions'=>array('create','update'), 'users'=>array('@'), ), array('allow', // allow admin user to perform 'admin' and 'delete' actions Chapter 8 [ 175 ] 'actions'=>array('admin','delete'), 'users'=>array('admin'), ), array('deny', // deny all users 'users'=>array('*'), ), ); } The filters() method is already familiar to us. It is where we specify all the lters to be used in the controller class. In this case, we have only one, accessControl, which refers to a lter provided by the Yii Framework. This lter uses the other method, accessRules(), which denes the rules that drive the access restrictions. In the accessRules() method mentioned previously, there are four rules specied. Each rule is represented as an array. The rst element of the array is either allow or deny. These indicate the granting or denying of access respectively. The rest of the array consists of name=>value pairs specifying the remaining parameters of the rule. Let's look at the rst rule dened previously: array('allow', // allow all users to perform 'index' and 'view' actions 'actions'=>array('index','view'), 'users'=>array('*'), ), This rule allows the index and view controller actions to be executed by any user. The asterisk '*' special character is a way to specify any user (anonymous, authenticated, or otherwise). The second rule is as follows: array('allow', // allow authenticated user to perform 'create' and 'update' actions 'actions'=>array('create','update'), 'users'=>array('@'), ), It allows for any authenticated user to access the create and update controller actions. The '@' special character is a way to specify any authenticated user. Iteration 5: User Access Control [ 176 ] The third rule is as follows: array('allow', // allow admin user to perform 'admin' and 'delete' actions 'actions'=>array('admin','delete'), 'users'=>array('admin'), ), This species that a specic user, named admin, is allowed to access the actionAdmin() and actionDelete() controller actions. The fourth rule is as follows: array('deny', // deny all users 'users'=>array('*'), ), It denies access to all controller actions to all users. Access rules can be dened using a number of context parameters. The previously mentioned rules dene actions and users to create the rule context, but there are several others listed as follows: • Controllers: This rule species an array of controller IDs to which the rule should apply. • Roles: This rule species a list of authorization items (roles, operation, permissions) to which the rule applies. This makes used of the RBAC feature we will be discussing in the next section. • Ips: This rule species a list of client IP addresses to which this rule applies. • Verbs: This rule species which HTTP request types (GET, POST, and so on) apply to this rule. • Expression: This rule species a PHP expression whose value indicates whether or not the rule should be applied. • Actions: This rule species the action method, by use of the corresponding action ID, to which the rule should match. • Users: This rule species the users to which the rule should apply. The current application user's name attribute is used for matching. Three special characters can also be used here: ° *: any user ° ?: anonymous users ° @: authenticated users [...]... RBAC relationships The Yii extension library (http://www.yiiframework.com/ extensions/) provides some packaged solutions for this Let's try out this new command Navigate to the root of your application and execute the shell command (Remember YiiRoot stands for where you have installed the Yii Framework): % YiiRoot/framework/yiic shell Yii Interactive Tool v1.1 (based on Yii v1.1.2) Please type 'help'... command, which is to be executed at the command line This will extend the command options of the yiic command-line tool we used to create our initial application Writing a console application command We introduced the yiic command-line tool back in Chapter 2, when we created a new HelloWorld! application, and again in Chapter 4 when we used it to initially create the structure of our TrackStar Web application. .. available with the yiic tool for creating these as well As a reminder, the yiic shell command allows you to interact with a web application on the command line You can execute it from the folder that contains the entry script for the application Then, within the context of the specific application, it provides tools to automatically generate new controllers, views and data models [ 182 ] Chapter 8 Console applications... interactive web application shell is configured to use our test database: % YiiRoot/framework/yiic shell protected/config/test.php Yii Interactive Tool v1.1 (based on Yii v1.1.2) Please type 'help' for help Type 'exit' to quit >> rbac This command will create three roles: Owner, Member, and Reader and the following premissions: create, read, update and delete user create, read, update and delete project... application The yiic tool is a console application in Yii that executes tasks in the form of commands We have used the webapp command to create a new applications, and back in Chapter 2, we also used the yiic shell command to create a new controller class We have been using the newer Gii code generator tool when initially creating our model classes and our CRUD scaffolding code However, there are commands available... the command is called The name of the class should be exactly the same as the desired command name, followed by Command In our case, our command will simply be rbac, so we'll name our class RbacCommand Lastly, in order to make this command available to the yiic console application, we need to save our class into the /protected/commands/shell/ folder So, create a new file called RbacCommand.php, and add... applications in Yii are easily extended by writing custom commands, and this is exactly what we are going to do We are going to extend the yiic shell command tool set by writing a new command-line tool to allow us to build our RBAC authorization hierarchy in a consistent and repeatable manner Writing a new command for a console application is quite simple It is simply a class that extends from CConsoleCommand... role FROM tbl_project_user_role WHERE project_ id=:projectId AND user_id=:userId AND role=:role"; $command = Yii: :app()->db->createCommand($sql); $command->bindValue(":projectId", $this->id, PDO::PARAM_INT); $command->bindValue(":userId", Yii: :app()->user->getId(), PDO::PARAM_INT); $command->bindValue(":role", $role, PDO::PARAM_STR); return $command->execute()==1 ? true : false; } This again executes the... the getHelp() method of our command class You can certainly be more verbose, and add more detail as desired Now let's run the command to establish the required hierarchy: >> rbac This command will create three roles: Owner, Member, and Reader and the following premissions: create, read, update and delete user create, read, update and delete project create, read, update and delete issue Would you like... user_id=:userId AND role=:role"; $command = Yii: :app()->db->createCommand($sql); $command->bindValue(":projectId", $this->id, PDO::PARAM_INT); $command->bindValue(":userId", $userId, PDO::PARAM_INT); $command->bindValue(":role", $role, PDO::PARAM_STR); return $command->execute(); } This simply deletes the row from the table that houses the association between the role, user and the project It will return . TrackStar Web application. The yiic tool is a console application in Yii that executes tasks in the form of commands. We have used the webapp command to create a new applications, and back in. command. Navigate to the root of your application and execute the shell command (Remember YiiRoot stands for where you have installed the Yii Framework): % YiiRoot/framework/yiic shell Yii. However, there are commands available with the yiic tool for creating these as well. As a reminder, the yiic shell command allows you to interact with a web application on the command line. You can

Ngày đăng: 09/08/2014, 12:22

Từ khóa liên quan

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

Tài liệu liên quan