Module remember me (duy trì đăng nhập) chuẩn

Hướng dẫn code chức năng remember me (duy trì đăng nhập) ở trang đăng nhập.

Tại sao chức năng remember me lại rất cần thiết?

Sau khi người dùng đăng nhập thành công thì server sẽ lưu giữ session (phiên) để ghi nhớ và xác nhận lại là người dùng đã đăng nhập. Tuy nhiên, thường thì session chỉ được lưu 25 phút tính từ lần thao tác gửi request lên server lần cuối cùng. Điều này có nghĩa là nếu bạn đã đăng nhập thành công vào tài khoản của mình trên một website, sau đó bạn treo máy và không làm gì cả (hoặc mở website khác ở cửa sổ khác), sau đó quay lại website đã đăng nhập ban đầu thì session đã không còn nữa và tài khoản của bạn đã tự động đăng xuất.

Điều này gây nên một số phiền toái như sau:

  • Ban soạn thảo một bài viết dài ở trình soạn thảo trên web, thời gian soạn thảo đến vài giờ đồng hồ nhưng khi bấm lưu thì tài khoản bị thoát ra và mất hết toàn bộ nội dung đã soạn.
  • Mỗi lần bạn tắt trình duyệt hoặc tắt máy, sau đó truy cập lại vào website thì cứ phải thực hiện gõ thông tin đăng nhập lại, một công việc lặp đi lặp lại thật là tốn thời gian và công sức.

Remember me sẽ giúp bạn giải quyết được các phiền toái trên.

Nhưng hãy cẩn thận

Sự vật nào cũng có 2 mặt. Remember me quả thật sẽ đem lại những lợi ích cụ thể nhưng nếu không cẩn thận thì có thể kẻ thiệt thòi chính là bạn.

  • Nếu bạn dùng máy tính công cộng nhưng lại tick chọn remember me, vậy thì bất kể ai sau đó sử dụng máy tính này đều có thể đăng nhập vào tài khoản của bạn mà không cần phải thực hiện thao tác đăng nhập.
  • Nếu bạn là lập trình viên xây dựng chức năng remember me nhưng không hiểu cách làm hoặc quy trình sơ sài, website bạn sẽ có lỗ hỏng ngay chính tại chức năng này.

Module remember (ở trang đăng nhập)

Quy trình

  1. Tại form đăng nhập bổ sung checkbox remember me.
  2. Khi người dùng submit, nếu có tick vào dấu này, tiến hành phát sinh ra 1 chuỗi random và lưu vào database, đồng thời cũng lưu vào cookie của trình duyệt.
  3. Như vậy ở các lần truy cập sau, nếu trình duyệt của người dùng có cookie và khớp với chuỗi đã lưu trong database thì chạy code giúp người dùng đăng nhập tự động.

Nguy hiểm: Một số coder chỉ lưu ID của thành viên vào cookie, sau đó kiểm tra nếu cookie có lưu ID thì sẽ tự động đăng nhập vào ID đó. Điều này là hết sức nguy hiểm vì cookie có thể dễ dàng làm giả, hacker có thể tận dụng cơ chế này tạo ra cookie với ID là ID của người dùng và ngang nhiên đăng nhập vào website dưới bất kỳ tài khoản nào mà không cần phải biết thông tin đăng nhập.

Model

Database: Nếu table chứa dữ liệu người dùng của bạn tên là user, hãy tạo thêm cột User_RememberMe với kiểu dữ liệu là text. Cột này sẽ ghi nhớ các chuỗi random là dữ liệu dùng để đối soát. Nếu cookie từ trình duyệt của người dùng khớp với một trong các chuỗi đang lưu trong cột này thì mới chạy code tự động đăng nhập.

Function: 

/* ********** ********** ********** ********** ********** ********** ********** ********** ********** **********  Update remember me  ********** ********** ********** ********** ********** ********** ********** ********** ********** ********** */  function login_tpl_update_user_remember_me($pdo){  	global $soc;  	$sql = "	UPDATE			`user`  			SET			`User_RememberMe`=:User_RememberMe  			WHERE			`User_ID`=:User_ID";  	return $soc->db->query($sql, $pdo);  }

View

Tại form đăng nhập method="post", bổ sung checkbox với name="remember_me".

Controller

// Đăng nhập thành công, lưu session  $_SESSION['user'] = $user;    // Remember me  if(isset($_POST['remember_me'])){  	// Chuỗi remember me  	$remember_me = substr(md5(date('YmdHis').rand(100000, 999999)), 0, 10);  	  	// Cập nhật chuỗi vào database  	$pdo = array(  		'User_RememberMe'=>$remember_me.','.$_SESSION['user']['User_RememberMe']  		,'User_ID'=>$_SESSION['user']['User_ID']  	);  	if(substr($pdo['User_RememberMe'], -1)==','){  		$pdo['User_RememberMe'] = substr($pdo['User_RememberMe'], 0, -1);  	}  	if(login_tpl_update_user_remember_me($pdo)){ // Cập nhật thành công  		$cooke_user = array(  			'id'=>$_SESSION['user']['User_ID']  			,'remember_me'=>$remember_me  		);  		setcookie('user', json_encode($cooke_user), time()+(3600*24*30), '/', $_SESSION['config']['domain']);  	}  }

Module tự động đăng nhập (ở tất cả mọi trang)

index.php

Bổ sung ngay bên dưới cụm khai báo thư viện SOC PHP Framework để trộn MVC cho trang remember_me.tpl. Có nghĩa là code của trang remember_me.tpl sẽ luôn được gọi ở tất cả mọi trang.

/* ********** ********** ********** ********** ********** ********** ********** ********** ********** **********  Tự động đăng nhập  ********** ********** ********** ********** ********** ********** ********** ********** ********** ********** */  $soc->mvc->prepare('remember_me.tpl');  

Model

/* ********** ********** ********** ********** ********** ********** ********** ********** ********** **********  Lấy thông tin thành viên dựa vào cookie  ********** ********** ********** ********** ********** ********** ********** ********** ********** ********** */  function remember_me_tpl_get_user($id, $remember_me){  	global $soc;  	$sql = "	SELECT			*  				FROM			`user`  				WHERE			`User_ID`=:User_ID  								AND FIND_IN_SET(:User_RememberMe, `User_RememberMe`)  				LIMIT			0, 1";  	$pdo = array(  		'User_ID'=>$id,  		'User_RememberMe'=>$remember_me  	);  	$rs = $soc->db->query($sql, $pdo);  	if(isset($rs[0])){  		return $rs[0];  	}  	return array();  }  

Controller

/* ********** ********** ********** ********** ********** ********** ********** ********** ********** **********  Thành viên đã đăng nhập thì dừng  ********** ********** ********** ********** ********** ********** ********** ********** ********** ********** */  if(isset($_SESSION['user'])){  	return;  }            /* ********** ********** ********** ********** ********** ********** ********** ********** ********** **********  Khai báo biến  ********** ********** ********** ********** ********** ********** ********** ********** ********** ********** */  // Mảng lọc & sắp xếp  $get = array(  	'id'=>''  	,'remember_me'=>''  );            /* ********** ********** ********** ********** ********** ********** ********** ********** ********** **********  Mảng lọc & sắp xếp  ********** ********** ********** ********** ********** ********** ********** ********** ********** ********** */  if(isset($_COOKIE['user'])){  	$temp = json_decode($_COOKIE['user'], true);  	foreach($temp as $k=>$v){  		if(isset($get[$k])){  			$get[$k] = trim($v);  		}  	}  }            /* ********** ********** ********** ********** ********** ********** ********** ********** ********** **********  Tự động đăng nhập  ********** ********** ********** ********** ********** ********** ********** ********** ********** ********** */  if($get['id'] && $get['remember_me']){  	$user = remember_me_tpl_get_user($get['id'], $get['remember_me']);  	if(count($user)){  		$_SESSION['user'] = $user;  		setcookie('user', json_encode($get), time()+(3600*24*30), '/', $_SESSION['config']['domain']);  	}  }
09-08-2021

Bài viết liên quan