Chức năng quên mật khẩu php

Khi người dùng đã tạo tài khoản trên website, nhưng không nhớ mật khẩu để đăng nhập. Giả sử chúng ta đã tạo chức năng đăng nhập với hai thông tin là tên đăng nhậpmật khẩu. Vậy, trong trường hợp này, chúng ta có thể tạo chức năng quên mật khẩu để người dùng có thể tự đổi lại mật khẩu của mình. 

Điều kiện tạo được chức năng quên mật khẩu

Không phải khi nào chúng ta cũng có thể tạo được chức năng quên mật khẩu, hay nói cách khác là chức năng đổi mật khẩu khi không nhớ mật khẩu cũ. Điều kiện tiên quyết để có thể tạo được chức năng này gồm:

1. Ngoài cặp username/ password, hệ thống lưu trữ người dùng phải có cách khác để nhận biết người dùng, ví dụ email, số điện thoại. Trong phạm vi bài viết, mình sẽ giới thiệu phương pháp sử dụng email. Như vậy, email phải là duy nhất cho mỗi người dùng.

2. Hệ thống phải có khả năng gửi thông tin qua phương pháp nhận biết người dùng tương ứng, ví dụ trong trường hợp của mình, hệ thống phải có khả năng gửi được email tự động.

Hướng dẫn từng bước tạo chức năng quên mật khẩu

1. Tạo bảng "reset_pass" trong database dùng để lưu thông tin yêu cầu đổi mật khẩu, code tạo table:

CREATE TABLE `reset_pass` (
  `id` INT(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
  `m_email` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  `m_token` varchar(256) COLLATE utf8_unicode_ci NOT NULL,
  `m_time` bigint(20) NOT NULL,
  `m_numcheck` tinyint(4) NOT NULL DEFAULT '0'
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

2. Tại trang đăng nhập, hiển thị nút "quên mật khẩu"

Chức năng quên mật khẩu php

3. Khi người dùng nhấn vào nút "quên mật khẩu", hiển thị form yêu cầu đổi mật khẩu, form này cho phép người dùng nhập vào email của mình kèm theo nút "tiếp theo". Các bạn có thể hiển thị form này trong một màn hình mới hoặc hiển thị bằng dialog tùy thích.

Chức năng quên mật khẩu php

4. Khi người dùng nhấn vào nút "tiếp theo", thực hiện xử lý và gửi kết quả vào email người dùng, đồng thời thông báo kết quả lên màn hình với nội dung: "chúng tôi đã gửi thông tin đặt lại mật khẩu vào email của bạn, vui lòng kiểm tra email và làm theo hướng dẫn". Giả sử, chúng ta đặt tên file xử lý này là "forgotPasswordProcess.php", mình sẽ trình bày chi tiết file này ngay bên dưới.

5. Tạo file "resetPassword.php" cho phép người dùng đặt lại mật khẩu mới, mình sẽ trình bày chi tiết file này ngày bên dưới.

Xử lý và trả kết quả khi người dùng quên mật khẩu

Chúng ta tiếp tục thực hiện file "forgotPasswordProcess.php". Đầu tiên, mình xin trình bày về luồng hoạt động tổng quan cần thiết trong file này như sau:

1. Nhận tên email mà người đùng đã nhập vào form yêu cầu đổi mật khẩu phía trên.

2. Tìm người dùng có email tương ứng trong bảng "user" (Giả định rằng mình lưu thông tin người dùng trong bảng này).

3. Tạo một chuỗi ngẫu nhiên có độ dài tương đối, ví dụ chuỗi ngẫu nhiên 16 ký tự.

4. Thêm mới một record vào bảng "reset_pass", với thông tin các field như sau:

  • id: không cần truyền vào, cái này là khóa chính, và mình đã đặt thành "auto increment" trước đó.
  • m_email: là địa chỉ email nhận được ở bước 1.
  • m_time: timestamp ở thời điểm hiện tại, các bạn có thể dùng hàm time() của php.
  • m_numcheck: không cần truyền vào, mặc định giá trị này sẽ bằng "0" khi mới thêm vào như định nghĩa của bảng phía trên.
  • m_token: mã hóa một chiều chuỗi ký tự ngẫu nhiên đã tạo tại bước 3. Các bạn có thể sử dụng hàm md5($string) của php.

5. Gửi đường link reset pass cho người dùng thông qua email nhận được ở bước 1. Đường link reset pass sẽ có dạng: 

Nhấn vào đây để tiến hành đặt lại mật khẩu

Trong đó:

{email} = mã hóa base64 của email nhận được ở bước 1. Các bạn có thể dùng hàm base64_encode($email) của php.

{key} = chuỗi ký tự ngẫu nhiên đã tạo tại bước 3.

Xử lý form đặt lại mật khẩu mới

Chúng ta tiếp tục thực hiện file "resetPassword.php". File này cho phép người dùng đặt lại mật khẩu mới. Mình xin trình bày cách hoạt động của file này như sau:

1. Lấy địa chỉ email và key thông qua phương thức GET.

2. Tìm record trong bảng "reset_pass" với điều kiện m_email = $email. Nếu tìm được chuyển đến bước 3, nếu không tìm được thì thông báo lỗi và kết thúc.

3. Kiểm tra md5($key) với m_token của record  tìm được tại bước 2. Nếu kết quả so sánh không giống nhau, tăng m_numcheck

 của record tìm được ở bước 2 lên 1. Nếu m_numcheck lớn hơn 3 thì xóa record đã tìm được ở bước 2. Nếu kết quả so sánh giống nhau thì kiểm tra m_time() so với thời gian hiện tại, nếu lớn hơn 1 ngày thì xóa record đã tìm được ở bước 2, nếu ít hơn hoặc bằng 1 ngày (24*60 phút) thì chuyển đến bước 4.

4. Nếu nhận được thông tin đổi mật khẩu thì chuyển đến bước 4.2, nếu không có thông tin đổi mật khẩu thì chuyển đến bước 4.1. Ghi chú: thông tin đổi mật khẩu gồm "mật khẩu mới" và "lặp lại mật khẩu mới".

4.1. Hiển thị form nhập thông tin đổi mật khẩu gồm 2 ô nhập liệu cho "mật khẩu mới" và "lặp lại mật khẩu mới". Action của form các bạn vẫn để là trang hiện tại.


4.2. Tại bước này các bạn sẽ nhận được thông tin gồm: "mật khẩu mới" và "lặp lại mật khẩu mới". Chúng ta sẽ tiến hành so sánh hai thông tin này, nếu giống nhau thì cập nhật mật khẩu thành "mật khẩu mới" cho người dùng có email bằng với email nhận được tại bước 1, thông báo thành công, xóa record đã tìm được trong bước 2, và kết thúc. Nếu "mật khẩu mới" và "lặp lại mật khẩu mới" không giống nhau thì chuyển đến bước 4.1 (Hiển thị lại form nhập thông tin đổi mật khẩu).

Các câu hỏi thường gặp khi thực hiện chức năng quên mật khẩu trong php

1. Làm thế nào để có thể thực hiện gửi email trong php ?

Trả lời:

Để tự động gửi email trong php, cách đơn giản nhất là sử dụng hàm mail() trong php (hỗ trợ PHP 4, PHP 5, PHP 7, PHP 8).

2. Vì sao phải mã hóa base64 địa chỉ email trong đường link đặt lại mật khẩu ? 

Trả lời:

Để ngăn chặn các ký tự đặc biệt xuất hiện trong đường link, nhằm tránh dẫn đến các sai sót khi so khớp kết quả.

3. Vì sao phải mã hóa md5($key) khi thực hiện chèn vào database ?

Trả lời:

Cũng giống như lý do các bạn phải mã hóa mật khẩu khi lưu xuống database vậy, nhằm trong trường hợp xấu nhất, bạn bị mất database vào tay của hacker, thì mật khẩu của người dùng vẫn không bị lộ. md5 chỉ mới là một ví dụ để mã hóa, và bạn có thể sử dụng các phương pháp tốt hơn như sha1 kèm theo các thủ thuật mã hóa khác mà tôi sẽ giới thiệu ở những bài viết sau.