CakePHP中文手册【翻译】-实例:简单的用户认证
实例:简单的用户认证
第1节
大蓝图
加入你是一个CakePHP新手,你应该会有很强的意愿复制和粘贴本代码,并在你的关键的,数据敏感处理产品应用程序中使用。抵制他们:本章是Cake内部的一个讨论,不具有应用安全性。在我疑惑我们提供任何相当明显的安全缺陷时,本实例的关键点是向你说明Cake的内部是如何工作的,并允许你创建一个你自己拥有的应用程序防弹衣。
Cake通过它内建的ACL引擎控制访问,那么用户认证和持久性呢?他们又怎样呢?
好,到目前为止,我们已经发现用户认证系统从一个应用到另外一个应用不停的在改变。像密码,其他,LDAP认证-以及大多数应用程序都有User
model,他们之间仅仅只有细微差别而已。现在,我们把它留给你。它会改变吗?我们不太确定。目前我们认为将它构建到框架里的额外支出是不值得那么做的,因为使用Cake来创建你自己的用户认证是非常简单的。
你需要3样东西:
1.一种验证用户的方法(通常完成是通过验证一个用户名和密码组合的用户身份).
2.一种持久跟踪用户的方法,因为他们引导你的应用程序(通常利用session完成)。
3.一种检验一个用户已经通过认证的方法(也常常和session交互来完成)的方法。
在本例中,我们将为一个客户管理系统创建一个简单的用户认证。这个虚构的应用程序很有可能被一个办公人员来跟踪联系人信息,以及客户的相关注释。本系统所有的功能会安排在我们的用户验证系统之后,除了一些少量的骨架以及公共安全的view,这些view仅显示存储在系统里的客户的名字以及职位。
我们从如何验证一个试图访问系统的用户这里开始。使用Cake的Session组件来存储通过验证的用户信息。一旦我们从session里得到用户信息,我们需要在应用程序里放入检查,以确保应用程序的用户不会进入他们不该去的地方。
需要注意的一件事情是,身份验证和访问控制不一样。在本例后面的所有东西都是关于如何看那些人是否是他们所说的那些人,并且允许他们有访问部分应用程序的基本权利。如果你想好好的润色一下这个访问,参看Cake ACL那章。我们需要对ACL适合的地方做出一些说明,但是现在,还是让我们把注意力放在简单的用户认证吧。
我也应该说这并不代表在应用程序安全性中,它是入门的。我们仅仅是想让你充分的利用它,以至你能够建立你自己的安全应用程序。
第2节
验证和持久
首先,我们需要一种方法来存储那些想访问我们客户管理系统的用户的信息。我们正在使用的客户管理系统在一个数据库表中存储用户信息,可以使用下面的SQL语句来创建此数据库表:
表 'users', 虚构的客户管理系统数据库
CREATE TABLE `users` (
`id` int(11) NOT NULL auto_increment,
`username` varchar(255) NOT NULL,
`password` varchar(32) NOT NULL,
`first_name` varchar(255) NOT NULL,
`last_name` varchar(255) NOT NULL, PRIMARY KEY
(`id`) ) |
相当简单,对不对?此表的Cake Model也非常简单:
<?php class User
extends AppModel { var $name = 'User'; } ?> |
我们需要的第一件东西就是一个登录view以及动作。它为应用程序用户提供一种方法来试图登录,并且也为系统提供一方法来处理信息,并看看他们是否被允许访问系统。view仅仅是一个HTML表单,并在Cake的HTML Helper的帮助下创建:
/app/views/users/login.thtml
<?if ($error): ?> <p>The login credentials you supplied
could not be recognized. Please try again.</p> <? endif;
?> <form action="<?php echo
$html->url('/users/login'); ?>" method="post"> <div>
<label for="username">Username:</label>
<?php echo $html->input('User/username',
array('size' => 20)); ?> </div> <div>
<label for="password">Password:</label>
<?php echo $html->password('User/password',
array('size' => 20)); ?> </div> <div>
<?php echo $html->submit('Login');
?> </div> </form> |
本view展示了一个简单的登录表单供用户登录系统。本表单的动作是/users/login, 它在 UsersController里,看起来如下::
/app/controllers/users_controller.php
(部分)
<?php class UsersController extends
AppController { function login() {
//Don't show the
error message if no data has been submitted.
$this->set('error', false);
// If a user has submitted form data:
if (!empty($this->data))
{
// First, let's see
if there are any users in the database
// with the username supplied by the user using the form:
$someone = $this->User->findByUsername($this->data['User']['username']);
// At this point,
$someone is full of user data, or its empty.
// Let's compare the form-submitted password with the one in
// the database.
if(!empty($someone['User']['password']) && $someone['User']['password'] == $this->data['User']['password'])
{ // Note: hopefully your password in the DB is hashed, // so your comparison might
look more like: // md5($this->data['User']['password'])
== ... // This means they were the
same. We can now build some basic // session information to
remember this user as 'logged-in'. $this->Session->write('User',
$someone['User']); // Now that we have them stored in a session, forward
them on // to a landing page for the
application. $this->redirect('/clients');
}
// Else, they
supplied incorrect data:
else
{ // Remember the $error var in the view? Let's set that
to true: $this->set('error',
true);
}
} } function logout() {
// Redirect users
to this action if they click on a Logout button.
// All we need to do here is trash the session information:
$this->Session->delete('User');
// And we should
probably forward them somewhere, too...
$this->redirect('/'); } } ?> |
并不是太坏:如果简单的话,login()动作的内容不会低于20行。本动作的结果要么是1:会将用户信息放入session,并前进到应用程序的主要页面,或者是2:返回到登录界面,并显示登录表单(并带有附加的错误信息).
第3节
访问应用程序的检验
既然我们可以对用户进行身份验证,还是让我们实现它,以至应用程序可以剔出从其他地方试图进入系统的用户,而非登录界面和我们在前面提到的‘基本'客户目录。
实现此的一种方法是在AppController里创建一个函数,此函数会为你进行session检查和踢出。
/app/app_controller.php
<?php class AppController extends
Controller { function checkSession() {
// If the session
info hasn't been set...
if (!$this->Session->check('User'))
{
// Force the user
to login
$this->redirect('/users/login');
exit();
} } } ?> |
现在你有一个可以在任何controller里使用的函数来确保用户在没有事先登录时,不可以访问controller动作。只要它正好是,你可以在任何级别上检查访问-这里是一些例子:
在Controller的所有动作前强制进行身份验证
<?php class NotesController extends
AppController { // Don't want non-authenticated users
looking at any of the actions
// in this controller? Use a beforeFilter to have Cake run
checkSession
// before any action logic. function beforeFilter() {
$this->checkSession(); } } ?> |
在单个Controller动作前强制进行身份验证
<?php class NotesController extends
AppController { function publicNotes($clientID) {
// Public access to
this action is okay... } function edit($noteId) {
// But you only
want authenticated users to access this action.
$this->checkSession(); } } ?> |
既然你有了基础,你可能想冒些险,实现一些在这里描绘的高级的,或者自定义的特性。与Cake的ACL组件集成或许是一个好的开端吧。