CakePHP中文手册【翻译】-实例:简单的用户认证

实例:简单的用户认证

1

大蓝图

加入你是一个CakePHP新手,你应该会有很强的意愿复制和粘贴本代码,并在你的关键的,数据敏感处理产品应用程序中使用。抵制他们:本章是Cake内部的一个讨论,不具有应用安全性。在我疑惑我们提供任何相当明显的安全缺陷时,本实例的关键点是向你说明Cake的内部是如何工作的,并允许你创建一个你自己拥有的应用程序防弹衣。

Cake通过它内建的ACL引擎控制访问,那么用户认证和持久性呢?他们又怎样呢?

好,到目前为止,我们已经发现用户认证系统从一个应用到另外一个应用不停的在改变。像密码,其他,LDAP认证-以及大多数应用程序都有User model,他们之间仅仅只有细微差别而已。现在,我们把它留给你。它会改变吗?我们不太确定。目前我们认为将它构建到框架里的额外支出是不值得那么做的,因为使用Cake来创建你自己的用户认证是非常简单的。

你需要3样东西:

1.一种验证用户的方法(通常完成是通过验证一个用户名和密码组合的用户身份).

2.一种持久跟踪用户的方法,因为他们引导你的应用程序(通常利用session完成)。

3.一种检验一个用户已经通过认证的方法(也常常和session交互来完成)的方法。

在本例中,我们将为一个客户管理系统创建一个简单的用户认证。这个虚构的应用程序很有可能被一个办公人员来跟踪联系人信息,以及客户的相关注释。本系统所有的功能会安排在我们的用户验证系统之后,除了一些少量的骨架以及公共安全的view,这些view仅显示存储在系统里的客户的名字以及职位。

我们从如何验证一个试图访问系统的用户这里开始。使用CakeSession组件来存储通过验证的用户信息。一旦我们从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表单,并在CakeHTML 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();

    }

}

?>

既然你有了基础,你可能想冒些险,实现一些在这里描绘的高级的,或者自定义的特性。与CakeACL组件集成或许是一个好的开端吧。

Last Updated:2006年12月5日
posted @ 2006-11-30 09:56  张太国  阅读(...)  评论(...编辑  收藏