Ngu ngơ học làm web (x33) - CakePHP2 - Đổi mật khẩu, ràng buộc ở controller

Tiếp theo của: Ngu ngơ học làm web (x32) - CakePHP2 – getUser, chỉ thực hiện khi đã đăng nhập
-----

Phần x33. CakePHP2 – Đổi mật khẩu, ràng buộc ở controller


Xem (clip số 35a – chickenrainshop):

- Đổi mật khẩu cho người dùng

- Ràng buộc mật khẩu tại controller (7":02)

- Kiểm tra thỏa ràng buộc - validates (8":53)

- strcmp (12":20)

Đổi mật khẩu cho người dùng:

Vào tập tin default.ctp để tạo link cho mục ‘Đổi mật khẩu’ trên giao diện.

[default.ctp]

<li><a href="">Cập nhật thông tin</a></li>
            <li><?php echo $this->Html->link('Đổi mật khẩu', '/doi-mat-khau'); ?></li>
            <li><a href="">Lịch sử mua hàng</a></li>
            <li><?php echo $this->Html->link('Đăng xuất', '/logout'); ?></li>

Vào UsersController.php để viết hàm change_password:

[UsersController.php]

            public $components = array('Paginator');

/**
 * đổi mật khẩu
 */
            public function changePassword() {
                        $this->set('title_for_layout', 'Đổi mật khẩu');
            }

Vào routes.php để thực hiện route cho chức năng ‘doi-mat-khau’:

[routes.php]

Router::connect('/login', ['controller' => 'users', 'action' => 'login']);
Router::connect('/doi-mat-khau', ['controller' => 'users', 'action' => 'changePassword']);

Tạo view cho action changePassword:

[View\Users\change_password.ctp]

<div class="panel panel-info">
            <h4 class="panel-heading"><span class="glyphicon glyphicon-user"> Đổi mật khẩu</span></h4>
            <?php if (!empty($userInfo)): ?>
                        <?php echo $this->Flash->render('auth'); ?>
                        <?php echo $this->Form->create('User', ['class' => 'form-horizontal', 'novalidate' => true, 'inputDefaults' => ['label' => false]]); ?>
                                    <div class="control-group">
                                                <label class="control-label" for="inputUsername">Mật khẩu mới</label>
                                                <div class="controls">
                                                            <?php echo $this->Form->input('password', ['placeholder' => 'Nhập mật khẩu mới']); ?>
                                                </div>
                                    </div>
                                    <div class="control-group">
                                                <label class="control-label" for="inputPassword">Xác nhận mật khẩu</label>
                                                <div class="controls">
                                                            <?php echo $this->Form->input('confirmPassword', ['placeholder' => 'Xác nhận mật khẩu', 'type' => 'password']); ?>
                                                </div>
                                    </div>
                                    <div class="control-group">
                                                <div class="controls">
                                                            <?php echo $this->Form->button('Lưu', ['type' => 'submit', 'class' => 'col-lg-2 btn btn-primary']); ?>
                                                </div>
                                    </div>
                        <?php echo $this->Form->end(); ?>
            <?php else: ?>
                        Bạn chưa đăng nhập, bấm vào <?php echo $this->Html->link('đây', '/login'); ?> để đăng nhập.
            <?php endif ?>
</div>

Ràng buộc dữ liệu cho trường password và confirmPassword:

[Model\User.php]

'password' => array(
                                    'notBlank' => array(
                                                'rule' => array('notBlank'),
                                                'message' => 'Mật khẩu không được để trống',
                                                //'allowEmpty' => false,
                                                //'required' => false,
                                                //'last' => false, // Stop validation after this rule
                                                //'on' => 'create', // Limit validation to 'create' or 'update' operations
                                    ),
                                    'minlength' => array(
                                                'rule' => array('minlength', 5),
                                                'message' => 'Mật khẩu ít nhất là 5 kí tự',
                                    )
                        ),
                        'confirmPassword' => array(
                                    'notBlank' => array(
                                                'rule' => array('notBlank'),
                                                'message' => 'Mật khẩu không được để trống',
                                    )
                        ),
                        'email' => array(

Hiển thị thông báo lỗi lên view:

[change_password.ctp]

<?php echo $this->Flash->render('auth'); ?>
                        <?php echo $this->element('errors'); ?>
                        <?php echo $this->Form->create('User', ['class' => 'form-horizontal', 'novalidate'

Không hiển thị thông báo lỗi ngay dưới input:

[change_password.ctp]

<?php echo $this->Form->input('password', ['placeholder' => 'Nhập mật khẩu mới', 'error' => false]); ?>
<?php echo $this->Form->input('confirmPassword', ['placeholder' => 'Xác nhận mật khẩu', 'type' => 'password', 'error' => false]); ?>

Viết tiếp xử lý trong action changePassword:

if ($this->User->validates()) {
            //trrcmp trả về 0 nếu giống nhau
            if (strcmp($this->request->data['User']['password'], $this->request->data['User']['confirmPassword']) == 0) {
                                                } else {
                                                            $this->Flash->error('Xác nhận mật khẩu không đúng.',
                                                                        ['params' => [
                                                                                    'class' => 'alert alert-danger' 
                                                                                    ]
                                                                        ]);
                                                }
                                    } else {

                                                $this->set('errors', $this->User->validationErrors);
-----------
Cập nhật 29/6/2017
-----------
Xem thêm:
Tổng hợp các bài viết về Ngu ngơ học làm web

Ngu ngơ học làm web (x32) - CakePHP2 - getUser, chỉ thực hiện khi đã đăng nhập

Tiếp theo của: Ngu ngơ học làm web (x31) - CakePHP2 – beforeFilter, lấy thông tin user, virtualFields
-----

Phần x32. CakePHP2 – getUser, chỉ thực hiện khi đã đăng nhập


Xem (clip số 34b – chickenrainshop):

- Ràng buộc login trên các form

Chỉ hiển thị ô ‘gửi nhận xét’ nếu người dùng đã đăng nhập:

[View\Books\view.ctp]

<p class="comment">
<strong><?php echo $comment['User']['fullname']; ?>:</strong>
<?php echo $comment['Comment']['content']; ?>
</p>
<!-- gửi nhận xét -->
<h4>Gửi nhận xét</h4>
<?php if (!empty($userInfo)): ?>
            <?php echo $this->element('errors'); ?>
            <?php echo $this->Flash->render(); ?>
            <?php echo $this->Form->create('Comment', ['url' => ['action' => 'add'], 'novalidate' => true, 'class' => 'comments form']); ?>
            <?php
            // bỏ trường này đi để đảm bảo an toàn thông tin
            // echo $this->Form->input('user_id',
            //          [
            //          'type' => 'text',
            //          'value' => 1,
            //          'hidden' => true,
            //          'label' => '',
            //          'required' => false
            //          ]);
            echo $this->Form->input('book_id',
                        [
                        'type' => 'text',
                        'hidden' => true,
                        'label' => '',
                        'required' => false,
                        'value' => $book['Book']['id']
                        ]);
            echo $this->Form->input('content', ['label' => '', 'rows' => 5, 'class' => 'col-lg-12']);
            ?>
            <?php echo $this->Form->button('Gửi', ['type' => 'submit', 'class' => 'pull-right btn btn-primary col-lg-3 send-button']); ?>
            <?php echo $this->Form->end(); ?>
<?php else: ?>
            Bạn phải <?php echo $this->Html->link('đăng nhập', '/login'); ?> trước khi đánh giá.
<?php endif ?>

Ở đoạn mã trên đã xóa bỏ thông tin về user_id, do vậy trong [action add() Controller\CommentsController.php] không thể lấy giá trị user_id từ view, mà sẽ gán giá trị cho user_id tại controller:

[action add() trong Controller\CommentsController.php]

public function add() {
                        if ($this->request->is('post')) {
                                    $this->Comment->set($this->request->data);
                                    if ($this->Comment->validates()) {
                                                $this->Comment->create();
                                                $userInfo = $this->getUser();
                                                $this->request->data['Comment']['user_id'] = $userInfo['id'];
                                                if ($this->Comment->save($this->request->data)) {


Sửa lỗi liên quan đến biến ‘fullname’:

[action view() trong BooksController.php]

$this->loadModel('Comment');
                        $comments = $this->Comment->find('all', [
                                                'conditions' => [
                                                            'book_id' => $book['Book']['id']
                                                            ],
                                                'order' => ['Comment.created' => 'asc'],
                                                'contain' => ['User' => ['fullname']]

                                    ]);
                        $this->set('comments', $comments);

Chỉ hiển thị thông tin về thanh toán, nếu người dùng đã đăng nhập:

[View\Books\view_cart.ctp]

            <!-- customer info -->
            <div class="panel panel-info col col-lg-7 col-lg-offset-1">
                        <h4 class="panel-heading"><span class="glyphicon glyphicon-user"></span>Thanh toán đơn hàng</h4>
                        <?php //if (true): ?>
                        <?php if (!empty($userInfo)): ?>
                                    <?php echo $this->Flash->render('order'); ?>
                                    <?php echo $this->Form->create('Order', ['url' => ['action' => 'checkout'], 'class' => 'form-horizontal', 'inputDefaults' => ['label' => false]]); ?>
                                    <div class="row">
                                                <?php echo $this->Form->label('name', 'Tên', ['class' => 'col col-lg-3 control-label']); ?>
                                                <div class="col col-lg-9">
                                                            <?php echo $this->Form->input('name', ['placeholder' => 'Nhập tên', 'value' => $userInfo['fullname']]); ?>
                                                </div>
                                    </div>
                                    <div class="row">
                                                <?php echo $this->Form->label('email', 'Email', ['class' => 'col col-lg-3 control-label']); ?>
                                                <div class="col col-lg-9">
                                                            <?php echo $this->Form->input('email', ['placeholder' => 'Nhập email', 'value' => $userInfo['email']]); ?>
                                                </div>
                                    </div>
                                    <div class="row">
                                                <?php echo $this->Form->label('address', 'Địa chỉ', ['class' => 'col col-lg-3 control-label']); ?>
                                                <div class="col col-lg-9">
                                                            <?php echo $this->Form->input('address', ['placeholder' => 'Nhập địa chỉ', 'value' => $userInfo['address']]); ?>
                                                </div>
                                    </div>
                                    <div class="row">
                                                <?php echo $this->Form->label('phone', 'Điện thoại', ['class' => 'col col-lg-3 control-label']); ?>
                                                <div class="col col-lg-9">
                                                            <?php echo $this->Form->input('phone', ['placeholder' => 'Nhập số điện thoại', 'value' => $userInfo['phone_number']]); ?>
                                                </div>
                                    </div>
                                    <div class="row">
                                                <div class="col col-lg-10 col-offset-2">
                                                            <?php echo $this->Form->button('Thực hiện thanh toán', ['type' => 'submit', 'class' => 'btn btn-primary pull-right']) ?>
                                                </div>
                                    </div>
                        <?php echo $this->Form->end(); ?>
                        <?php else: ?>
                                    Bạn phải đăng nhập trước khi thanh toán.
                        <?php endif ?>
            </div>
            <!-- end customer info -->

Chỉnh sửa cho action checkout() trong OrdersController.php:

public function checkout() {
                        if ($this->request->is('post')) {
                                    $userInfo = $this->getUser();
                                    $data = [
                                                'user_id' => $userInfo['id'],
                                                'order_info' => json_encode($this->Session->read('cart')),


Chỉnh sửa cho view Users\login.ctp:

<div class="panel panel-info">
            <h4 class="panel-heading"><span class="glyphicon glyphicon-user"></span></h4>
            <?php if (empty($userInfo)): ?>
                        <?php echo $this->Flash->render('auth'); ?>
                        <?php echo $this->Form->create('User', ['class' => 'form-horizontal', 'novalidate' => true, 'inputDefaults' => ['label' => false]]); ?>
                                    <div class="control-group">
                                                <label class="control-label" for="inputUsername">Username</label>
                                                <div class="controls">
                                                            <?php echo $this->Form->input('username', ['placeholder' => 'Tên đăng nhập']); ?>
                                                </div>
                                    </div>
                                    <div class="control-group">
                                                <label class="control-label" for="inputPassword">Password</label>
                                                <div class="controls">
                                                            <?php echo $this->Form->input('password', ['placeholder' => 'Mật khẩu']); ?>
                                                </div>
                                    </div>
                                    <div class="control-group">
                                                <div class="controls">
                                                            <?php echo $this->Form->button('Đăng nhập', ['type' => 'submit', 'class' => 'col-lg-2 btn btn-primary']); ?>
                                                </div>
                                    </div>
                        <?php echo $this->Form->end(); ?>
            <?php else: ?>
                        Bạn đã đăng nhập, bấm vào <?php echo $this->Html->link('đây', '/'); ?> để quay về trang chủ.
            <?php endif ?>

</div>
-----------
Cập nhật 23/6/2017
-----------
Xem thêm:
Tổng hợp các bài viết về Ngu ngơ học làm web

Ngu ngơ học làm web (x31) - CakePHP2 - beforeFilter, lấy thông tin user, virtualFields

Tiếp theo của: Ngu ngơ học làm web (x30) - CakePHP2 – Auth, đăng nhập, đăng xuất
-----

Phần x31. CakePHP2 – beforeFilter, lấy thông tin user, virtualFields


Xem (clip số 33b – chickenrainshop):

- Lọc các action không yêu cầu đăng nhập

- Sử dụng Auth->allow, beforeFilter (3":21)

- Sử dụng parent để không ghi đè hàm cha (8":15)

Mặc định AuthComponent sẽ tác động lên mọi action trong mọi controller của project. Nghĩa là người dùng vào bất kì trang nào, hoặc sử dụng bất kì chức năng nào của website, nó cũng bắt phải đăng nhập; hay nói cách khác mọi thao tác đều phải đăng nhập để hệ thống kiểm soát.

Tuy nhiên, trong thực tế, sẽ có những trang, những action không nhất thiết phải đăng nhập mới sử dụng được. Vì vậy, cần phải khai báo để website bỏ qua yêu cầu chứng thực đối với các trường hợp này. Khai báo trong hàm beforeFilter.

Đọc thêm về hàm beforeFilter tại đây: https://book.cakephp.org/2.0/en/controllers.html

[This function is executed before every action in the controller. It’s a handy place to check for an active session or inspect user permissions.

The beforeFilter() method will be called for missing actions, and scaffolded actions.]

Hàm beforeFilter được thực thi trước mọi action trong controller.

Trong hàm beforeFilter, sử dụng hàm $this->Auth->allow(); để liệt kê các action mà người sử dụng có thể dùng mà không cần đăng nhập. Ví dụ,

[AppController.php]

public function beforeFilter() {
                        $this->Auth->allow('menu', 'index');
            }

Do action ‘menu’, ‘index’ được chỉ định trong AppController, nên chỉ định này sẽ áp dụng cho mọi action ‘menu’, ‘index’ của mọi controller là con của AppController.

Nếu chỉ muốn thiết lập cho một controller cụ thể thì viết thêm hàm beforeFilter trong chính controller đó, và nhớ thêm dòng mã:

parent::beforeFilter();

để thực thi các nội dung được thiết lập tại hàm beforeFilter trong AppController. Ví dụ,

[CouponsController.php]

            public function beforeFilter() {
                        parent::beforeFilter();
                        $this->Auth->allow('add');
            }

Xem (clip số 34a – chickenrainshop):

Sau khi người dùng đăng nhập thành công, thông tin người dùng sẽ được lưu trong AuthComponent.
Để kiểm tra người dùng đăng nhập hay chưa? Sử dụng hàm:

$this->Auth->login()

Để lấy thông tin người dùng, sử dụng hàm:

$this->Auth->user();

Nội dung hàm lấy thông tin người dùng, trong AppController.php:

public function getUser() {
                        // kiểm tra người dùng đăng nhập hay chưa?
                        if ($this->Auth->login()) {
                                    // trả về thông tin người dùng
                                    return $this->Auth->user();
                        }
            }

Để gửi thông tin người dùng đã đăng nhập tới tất cả các view, sẽ thực hiện trong hàm beforeFilter tại AppController.php:

public function beforeFilter() {
                        $this->Auth->allow('menu', 'index');
                        $this->set('userInfo', $this->getUser());
            }

Trong các view, để kiểm tra xem người dùng đã đăng nhập hay chưa, sẽ kiểm tra biến userInfo:

[View\Layouts\default.ctp]

<!-- sidebar -->
<div class="sidebar col col-lg-3">
<!-- user panel -->
<?php if (!empty($userInfo)): ?>
            <div class="panel panel-info">
                        <h4 class="panel-heading"><span class="glyphicon glyphicon-user"></span><small> Xin chào <strong><?php echo $userInfo['username']; ?></strong></small></h4>
                        <ul>
                                    <li><a href="">Cập nhật thông tin</a></li>
                                    <li><a href="">Đổi mật khẩu</a></li>
                                    <li><a href="">Lịch sử mua hàng</a></li>
                                    <li><a href="">Đăng xuất</a></li>
                        </ul>
            </div>
<?php else: ?>
            <div class="panel panel-info">
                        <h4 class="panel-heading"><span class="glyphicon glyphicon-user"></span><small> Xin chào <strong>khách</strong></small></h4>
                        Nhấn vào <?php echo $this->Html->link('đây','/login'); ?> để đăng nhập.
            </div>
<?php endif ?>                      
<!-- /user panel -->

Thiết lập virtualFields:

Đọc thêm về virtualFields tại đây: https://book.cakephp.org/2.0/en/models/virtual-fields.html

VirtualFields cho phép tạo một tên trường ảo cho Model, tuy nhiên chỉ có thể đọc (read) dữ liệu từ trường này chứ không thể lưu xuống cơ sở dữ liệu (save).

Khai báo virtualFields trong model User:

[Model\User.php]

class User extends AppModel {
            public $virtualFields = [
                        'fullname' => 'concat(User.lastname, " ", User.firstname)'
            ];

Hàm concat để nối chuỗi.

Gọi ra sử dụng trong view:

[default.ctp]

<h4 class="panel-heading"><span class="glyphicon glyphicon-user"></span><small> Xin chào <strong><?php echo $userInfo['fullname']; ?></strong></small></h4>
            <ul>

                        <li><a href="">Cập nhật thông tin</a></li>
-----------
Cập nhật 22/6/2017
-----------
Xem thêm:
Tổng hợp các bài viết về Ngu ngơ học làm web

Ngu ngơ học làm web (x30) - CakePHP2 - Auth, đăng nhập, đăng xuất

Tiếp theo của: Ngu ngơ học làm web (x29) - CakePHP2 – saveAll(), array->JSON
-----

Phần x30. CakePHP2 – Auth, đăng nhập, đăng xuất


Xem (clip số 32 – chickenrainshop):

Trong website, có một số trang ai cũng có thể truy cập vào, tuy nhiên có một số trang cần phải đăng nhập thì mới truy cập được. Để làm điều này, cần phải có cơ chế đăng nhập và xác thực người dùng.

Đọc thêm để phân biệt: identifying (anh tên gì?), authenticating (có đúng là anh không?) và authorizing (mời anh đọc báo?).

CakePHP sử dụng AuthComponent để thực hiện việc xác thực người dùng.

Quy trình xây dựng một chức năng bằng CakePHP:

Bước 1: Khởi tạo
Bước 2: Xử lý
Bước 3: Hiển thị
Một chức năng có thể cần một form để gửi dữ liệu về server, hoặc cần tạo một view, hoặc chỉ cần sử dụng link/postLink
Viết xử lý trong các function (hay còn gọi là action) của controller. Sử dụng Model, hàm find hoặc các component
Hiển thị lại dữ liệu do action trả về lên View (nếu cần), hoặc chỉ gửi thông báo lên View (sử dụng Flash)

Xem (clip số 33a – chickenrainshop):

Khai báo sử dụng authcomponent trong AppController.php

class AppController extends Controller {
            public $components = [
                        'Flash','Session','Tool',
                        'Auth' =>[
                                    'loginAction' => '/login',
                                    'authError' => 'Bạn cần phải đăng nhập để tiếp tục!',
                                    'flash' => [
                                                            'element' => 'error',
                                                            'key' => 'auth',
                                                            'params' => ['class' => 'alert alert-danger']
                                                ],
                                    'loginRedirect' => '/'
                                    ]
                        ];

Trong đó,

- loginAction: trỏ tới action xử lý cho việc đăng nhập, ví dụ: 'loginAction' => '/login'.

- authError: chuỗi thông báo khi người dùng chưa đăng nhập, nhưng lại muốn thực hiện một chức năng có yêu cầu đăng nhập, ví dụ: 'authError' => 'Bạn cần phải đăng nhập để tiếp tục!'. Bản chất của authError hoạt động giống như một thông báo bằng Flash. Có thể thiết lập thêm các tham số cho authError.

- flash: định dạng cho chuỗi thông báo ‘authError’

- loginRedirect: trỏ tới trang sẽ được hiển thị, nếu đăng nhập thành công

Cấu hình route cho việc đăng nhập:

[routes.php]

Router::connect('/', ['controller' => 'books', 'action' => 'index']);
Router::connect('/sach-moi', ['controller' => 'books', 'action' => 'latest_books']);
Router::connect('/login', ['controller' => 'users', 'action' => 'login']);

Tạo action login trong UsersController.php:

/**
 * login - đăng nhập
 */
            public function login() {
                        $this->set('title_for_layout', 'Đăng nhập');
                       
            }

Tạo view login.ctp trong View\Users,

<div class="panel panel-info">
            <h4 class="panel-heading"><span class="glyphicon glyphicon-user"></span></h4>
            <?php echo $this->Flash->render('auth'); ?>
            <?php echo $this->Form->create('User', ['class' => 'form-horizontal', 'inputDefaults' => ['label' => false]]); ?>
                        <div class="control-group">
                                    <label class="control-label" for="inputUsername">Username</label>
                                    <div class="controls">
                                                <?php echo $this->Form->input('username', ['placeholder' => 'Tên đăng nhập']); ?>
                                    </div>
                        </div>
                        <div class="control-group">
                                    <label class="control-label" for="inputPassword">Password</label>
                                    <div class="controls">
                                                <?php echo $this->Form->input('password', ['placeholder' => 'Mật khẩu']); ?>
                                    </div>
                        </div>
                        <div class="control-group">
                                    <div class="controls">
                                                <?php echo $this->Form->button('Đăng nhập', ['type' => 'submit', 'class' => 'col-lg-2 btn btn-primary']); ?>
                                    </div>
                        </div>
            <?php echo $this->Form->end(); ?>
</div>

Do ở đây đang sử dụng phiên bản CakePHP 2.9.6, khác so với trong clip, nên làm theo clip sẽ bị một số vấn đề:

- sql_dump: sẽ không xuất ra mật khẩu đã được băm (hashed)

- nhập mật khẩu ở dạng rõ (plain-text), giống như trong cơ sở dữ liệu đang có, sẽ không vượt qua được quá trình chứng thực


Đọc thêm một ví dụ mẫu về chứng thực (authenticating) và phân quyền (authorizing) tại đây: https://book.cakephp.org/2.0/en/tutorials-and-examples/blog-auth-example/auth.html

Vấn đề đang gặp phải là:

- Khi lưu mật khẩu vào cơ sở dữ liệu, mật khẩu chưa được băm (hashing), vẫn ở dạng rõ (plain text)

- Tại form login, sau khi người dùng nhập mật khẩu,  bấm nút Đăng nhập, PHP sẽ băm mật khẩu này 
và so sánh với mật khẩu trong cơ sở dữ liệu

- Kết quả là mật khẩu đã được băm sẽ không thể khớp với mật khẩu đang ở dạng rõ trong cơ sở dữ liệu

Cách khắc phục:

Thực hiện băm mật khẩu của người dùng và lưu lại vào cơ sở dữ liệu. Sử dụng hàm 
Security::hash($yourPassword, NULL, true) để băm.

Ví dụ,

Giả sử mật khẩu dạng rõ là ‘1’, thực hiện băm mật khẩu này (trong view login.ctp):

<div class="panel panel-info">
<?php echo 'hashedPasswords = '.Security::hash(1, NULL, true); ?>
            <h4 class="panel-heading"><span class="glyphicon glyphicon-user"></span></h4>

Kết quả băm là: 5059a8afd49865c1bf27881d9cfd5a22657ca1a9

Lưu kết quả băm này vào cơ sở dữ liệu, thay thế cho giá trị ‘1’ trước đó.

Bây giờ, kiểm tra lại bằng cách đăng nhập với mật khẩu ‘1’ là được.

Nội dung action login trong UsersController.php:

/**
 * login - đăng nhập
 */
            public function login() {
                        if ($this->request->is('post')) {
                                    if ($this->Auth->login()) { // thực thi quá trình chứng thực
                                                $this->redirect($this->Auth->redirect()); // nếu chứng thực thành công, chuyển tới trang được thiết lập trong biến Auth -> loginRedirect
                                    } else {
                                                $this->Flash->error('Sai tên đăng nhập hoặc mật khẩu', ['key' => 'auth', 'params' => ['class' => 'alert alert-danger']]);
                                    }
                        }
                        $this->set('title_for_layout', 'Đăng nhập');
                       
            }

Quá trình đăng xuất:

Sử dụng AuthComponent để logout, nó sẽ redirect về một action nào đó, mặc định AuthComponent sẽ redirect về view login.

Viết action logout trong UsersController.php:

/**
 * logout - đăng xuất
 */
            public function logout() {
                        $this->redirect($this->Auth->logout());
            }

Viết thêm đoạn mã để route (trong  routes.php):


Router::connect('/logout', ['controller' => 'users', 'action' => 'logout']);
-----------
Cập nhật 21/6/2017
-----------
Xem thêm:
Tổng hợp các bài viết về Ngu ngơ học làm web