Tiếp tục ta sẽ dựng lại 'Forgot password' với xử lý cho auto reset password như sau.
- Đầu tiên ta sẽ
build form, các input controlers nó sẽ y hệt function
user_pass() trong .\modules\user\user.pages.inc
- Tiếp theo là
validate khi submit form, cũng sẽ y hệt function
user_pass_validate() trong .\modules\user\user.pages.inc
- Sẽ có thay đổi trong
submit form được dựng lại
p/s: code nguyên thủy trong function
user_pass_submit() trong .\modules\user\user.pages.inc
node 1: Code mới sẽ được custom bằng function
reset_password_content là function để tạo nội dung mail kích hoạt 'Forgot password' để mail có link kích hoạt khác đi, sau đó và dùng function
drupal_mail để gởi mail. Để dùng được drupal_mail, ta phải tạo hook_mail và truyền các thông số cần thiết đúng quy định thì cơ chế mail mới gởi đi được nếu không việc gởi thất bại!
note 2: code nguyên thủy Drupal sẽ gọi
_user_mail_notify() và trong đó bao gồm cả tạo nội dung mail và gởi mail kích hoạt có
link /
user/reset/uid/time_stamp/user_pass_hash
Code: Select all
function form_forgot_form_submit($form, &$form_state) {
$account = $form_state ['values'] ['account'];
$to = $form_state['values']['account']->mail;
$email_content = reset_password_content($form_state);
$params = array('body' => $email_content);
$key = 'active_password';
$from = variable_get('site_mail', ini_get('sendmail_from')); //$form_state['values']['from_email'];
//var_dump('ss_reset_password', $key, $to, language_default(), $params, $from);die;
$mail = drupal_mail('ss_password', $key, $to, language_default(), $params, $from);
if (! empty ( $mail )) {
watchdog ( 'user', 'Password reset request instructions mailed to %name at %email.', array (
'%name' => $account->name,
'%email' => $account->mail
) );
drupal_set_message ( t ( 'Further instructions have been sent to your e-mail address.' ) );
}
$form_state ['redirect'] = 'member_login';
return;
}
function reset_password_content
link kích hoạt sẽ dùng trong mail sẽ là /
activepass/reset/uid/time_stamp/user_pass_hash
node : user_pass_rehash function của Drupal sẽ tạo ra một giá trị hash để sử dụng trong URL mỗi người sử dụng phụ thuộc thời gian
Code: Select all
function reset_password_content($form_state)
{
$timestamp = REQUEST_TIME;
$account = $form_state['values']['account'];
$email_to = $form_state['values']['account']->mail;
$user_name = $form_state['values']['account']->name;
$one_time_login_url = url("activepass/reset/$account->uid/$timestamp/" . user_pass_rehash($account->pass, $timestamp, $account->login, $account->uid), array('absolute' => TRUE));
$body = t("$user_name,
A request to reset the password for your account has been made at tthlan.info.
You may now log in by clicking this link or copying and pasting it to your browser:
$one_time_login_url
This link can only be used once to log in and will lead you to a page where you can set your password. It expires after one day and nothing will happen if it's not used.
-- tthlan.info team");
return $body;
}
tham khảo thêm function user_pass_rehash () trong ./modules/user.module
Code: Select all
/**
* Creates a unique hash value for use in time-dependent per-user URLs.
*
* This hash is normally used to build a unique and secure URL that is sent to
* the user by email for purposes such as resetting the user's password. In
* order to validate the URL, the same hash can be generated again, from the
* same information, and compared to the hash value from the URL. The URL
* normally contains both the time stamp and the numeric user ID. The login
* timestamp and hashed password are retrieved from the database as necessary.
* For a usage example, see user_cancel_url() and user_cancel_confirm().
*
* @param string $password
* The hashed user account password value.
* @param int $timestamp
* A UNIX timestamp, typically REQUEST_TIME.
* @param int $login
* The UNIX timestamp of the user's last login.
* @param int $uid
* The user ID of the user account.
*
* @return
* A string that is safe for use in URLs and SQL statements.
*/
function user_pass_rehash($password, $timestamp, $login, $uid)
function ss_password_mail
hook_mail
ss_password, để thiết lập subject và body.
Để dùng chung cho gởi kích hoạc và gởi mail auto reset mới cho client.
Nên ở đây switch trên key để thiết lập riêng biệt cho từng trường hợp.
Code: Select all
/**
* Implements hook_mail()
* @param
* type $key to decide which email body to sent on basis of key parameter incense of multiple email content
* @param
* type $message the email content to be sent.Message array contains 'subject and body ' for the email.
* @param
* type $params using to get the cusotm email content from a function.This can be used in my other ways aslo as per need.
*/
function ss_password_mail($key, &$message, $params) {
$language = $message['language'];
//var_dump($key, $message, $params) ;die;
switch ($key) {
//switching on $key lets you create variations of the email based on the $key parameter
case 'active_password':
$message['subject'] = t('Active Reset Password Request');
//the email body is here, inside the $message array
$message['body'][] = $params['body'];
break;
case 'reset_password':
$message['subject'] = t('New Password Login');
//the email body is here, inside the $message array
$message['body'][] = $params['body'];
break;
}
}
- Để link click trên mail , ta phải tạo
hook_menu để drupal hiểu activepass link
node : hook_menu sẽ gọi function
ss_user_pass_reset
Code: Select all
$items['activepass/reset/%/%/%'] = array(
'title' => 'Reset password',
'page callback' => 'drupal_get_form',
'page arguments' => array('ss_user_pass_reset', 2, 3,4),
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
function ss_user_pass_reset
Hàm gần giống với function nguyên thủy user_pass_reset trong .\modules\user\user.pages.inc
Build lại function ss_user_pass_reset($form, &$form_state, $uid, $timestamp, $hashed_pass, $action = NULL)
khi client click nhấp link active forgot pass ở phần trước, system sẽ redirect client tới page để client click vào nút submit một lần duy nhất để
sau đó system sẽ gởi trực tiếp new auto generate new password có độ dài 8 ký tự tới email của user và auto login cho client sau khi submit.
note 1: trả về
một cấu trúc form khi vào activepass link
note 2: vẫn dùng
ss_password hook_mail với key '
reset_password' để gởi email với password mới
note 3: sau khi đối chiếu user_pass_hash và timestamp hợp lệ,
user_login_finalize là hàm tự động login và cập nhật timestamp trên database để việc xác nhận trên form active forgot password link chỉ dùng 1 lần.
node 4: trường hợp clien vào page của active link lần đầu mà ko nhấn nút submit xác nhận thì link đó vẫn dùng được trong 24h
node 5:
tạo ngẫu nhiên password
$edit['pass'] = user_password(8);
cập nhật password cho account user
$account = user_save($account, $edit);
Code: Select all
/**
* Menu callback; process one time login link and redirects to the user page on success.
*/
function ss_user_pass_reset($form, &$form_state, $uid, $timestamp, $hashed_pass, $action = NULL) {
global $user;
// When processing the one-time login link, we have to make sure that a user
// isn't already logged in.
if ($user->uid) {
// The existing user is already logged in.
if ($user->uid == $uid) {
//....
} // A different user is already logged in on the computer.
else {
//....
}
drupal_goto ( 'user_settings' );
} else {
// Time out, in seconds, until login URL expires. Defaults to 24 hours =
// 86400 seconds.
$timeout = variable_get ( 'user_password_reset_timeout', 86400 );
$current = REQUEST_TIME;
// Some redundant checks for extra security ?
$users = user_load_multiple ( array (
$uid
), array (
'status' => '1'
) );
if ($timestamp <= $current && $account = reset ( $users )) {
// No time out for first time login.
if ($account->login && $current - $timestamp > $timeout) {
drupal_set_message ( t ( 'You have tried to use a one-time login link that has expired. Please request a new one using the form below.' ), 'error' );
drupal_goto ( 'user_settings' );
} elseif ($account->uid && $timestamp >= $account->login && $timestamp <= $current && $hashed_pass == user_pass_rehash ( $account->pass, $timestamp, $account->login, $account->uid )) {
// First stage is a confirmation form, then login
if ($action == 'active') { // active reset password
// Set the new user.
$user = $account;
// user_login_finalize() also updates the login timestamp of the
// user, which invalidates further use of the one-time login link.
user_login_finalize ();
watchdog ( 'user', 'User %name used one-time login link at time %timestamp.', array (
'%name' => $account->name,
'%timestamp' => $timestamp
) );
// Generate auto password for active password request
$edit['pass'] = user_password(8);
$account = user_save($account, $edit);
// Email new generate password
$to = $user->mail ;
$email_content = new_password_content($account->name, $edit['pass']);
$params = array('body' => $email_content);
$key = 'reset_password';
$from = variable_get('site_mail', ini_get('sendmail_from')); //$form_state['values']['from_email'];
//var_dump('ss_reset_password', $key, $to, language_default(), $params, $from);die;
$mail = drupal_mail('ss_password', $key, $to, language_default(), $params, $from);
if (! empty ( $mail )) {
watchdog ( 'user', 'A new Password mailed to %name at %email.', array (
'%name' => $user->name,
'%email' => $user->mail
) );
drupal_set_message ( t ( 'You are logged in as ' . $account->name . '. A new password have been sent to your e-mail address.' ) );
}
drupal_goto ( 'user_settings' );
} else {
$form ['message'] = array (
'#markup' => t ( '<p>This is a one-time login for %user_name and will expire on %expiration_date.</p>'.
'<p>Click on this button to active your password request once time.</p>', array (
'%user_name' => $account->name,
'%expiration_date' => format_date ( $timestamp + $timeout )
) )
);
$form ['help'] = array (
'#markup' => '<p>' . t ( 'This active link can not be used after click this button.' ) . '</p>'
);
$form ['actions'] = array (
'#type' => 'actions'
);
$form ['actions'] ['submit'] = array (
'#type' => 'submit',
'#value' => t ( 'Submit' )
);
$form ['#action'] = url ( "activepass/reset/$uid/$timestamp/$hashed_pass/active" );
$form['#attributes']['class'] = 'tac'; // update action attribute
return $form;
}
} else {
//...
}
} else {
// Deny access, no more clues.
// Everything will be in the watchdog's URL for the administrator to check.
drupal_access_denied ();
drupal_exit ();
}
}
}