Làm thế nào tôi có thể chắc chắn rằng người dùng đã xác minh email của họ sau khi đăng ký?


7

Tôi đang làm việc trên một plugin sử dụng WordPress làm nhà cung cấp Đăng nhập một lần cho một ứng dụng khác. Tôi cần chắc chắn rằng người dùng đã xác minh địa chỉ email của họ bằng cách trả lời email được gửi bởi wp_new_user_notification().

Cho đến nay, cách tiếp cận tốt nhất mà tôi đã tìm thấy là nối vào after_password_resethành động và thêm user_metadata để chỉ ra rằng email đã được xác minh. Điều này hoạt động, nhưng tất cả những gì nó thực sự nói với tôi là reset_passwordchức năng đã được gọi.

Có cách nào tốt hơn để làm điều này?


2
Có lẽ empty( get_userdata( $user_id )->user_activation_key )nào?
Samuel Elh

Có vẻ như điều đó vẫn chỉ là reset_passwordđã được gọi. ( reset_passwordcác cuộc gọi wp_set_password, đó là nơi khóa kích hoạt được đặt thành ''.)
Simon Cossar

1
Điều gì về một bộ đếm mật khẩu tùy chỉnh đặt lại cho mỗi người dùng, được lưu trữ trong meta người dùng?
bạch dương

Câu trả lời:


3

Tôi đã thử một vài cách tiếp cận khác nhau để xác minh email của người dùng. Hiện tại, những gì tôi đang làm là đây:

Khi người dùng đăng ký lần đầu, hãy đặt user_metadata 'email_not_verified' của người dùng thành 1.

add_action( 'user_register', 'sc_user_email_not_verified' );
function sc_user_email_not_verified( $user_id ) {
  update_user_meta( $user_id, 'email_not_verified', 1 );
}

Sau đó, ghi đè wp_new_user_notificationchức năng để nó thêm 'email_verification_key' vào url đăng nhập. Nó cũng lưu khóa đó dưới dạng user_metadata.

function wp_new_user_notification( $user_id, $depreciated = null, $notify = '' ) {

...

$email_verification_key = wp_generate_password( 20, false );
update_user_meta( $user_id, 'email_verification_key', $email_verification_key );

$message = sprintf(__('Username: %s'), $user->user_login) . "\r\n\r\n";
$message .= __('To set your password, visit the following address:') . "\r\n\r\n";
$message .= '<' . network_site_url("wp-login.php?action=rp&key=$key&mail_key=$email_verification_key&login=" . rawurlencode($user->user_login), 'login') . ">\r\n\r\n";
$message .= wp_login_url() . "\r\n";

wp_mail($user->user_email, sprintf(__('[%s] Your username and password info'), $blogname), $message);
}

Sau đó, móc vào hành động 'validate_password_reset' để kiểm tra xem khóa xác minh email từ yêu cầu đặt lại mật khẩu có khớp với khóa đã lưu không. Nếu các khóa không khớp, hãy xóa người dùng và chuyển hướng họ trở lại biểu mẫu đăng ký với lỗi 'emailnotverified'. Nếu các khóa khớp nhau, hãy xóa siêu dữ liệu 'email_not_verified'.

add_action( 'validate_password_reset', 'sc_verify_user_email', 10, 2 );
function sc_verify_user_email( $errors, $user ) {
    if ( isset( $_REQUEST['mail_key'] ) ) {
        $email_verification_key = $_REQUEST['mail_key'];
        $saved_key              = get_user_meta( $user->ID, 'email_verification_key', true );

        if ( ! ( $email_verification_key === $saved_key ) ) {
            require_once( ABSPATH . 'wp-admin/includes/user.php' );
            wp_delete_user( $user->ID );
            wp_redirect( network_site_url( "wp-login.php?action=register&error=emailnotverified" ) );
            exit;
        } else {
            delete_user_meta( $user->ID, 'email_not_verified' );
        }
    }
}

Nếu email không được xác minh, hãy thêm một thông báo sẽ được hiển thị trên trang đăng ký khi có lỗi 'emailnotverified'.

add_filter( 'login_message', 'sc_email_not_verified_message' );
function sc_email_not_verified_message() {
    $action = isset( $_REQUEST['action'] ) ? $_REQUEST['action'] : '';
    $error = isset( $_REQUEST['error'] ) ? $_REQUEST['error'] : '';

    if ( 'register' === $action && 'emailnotverified' === $error ) {
        $message = '<p class="message">' . __( 'Your email address could not be verified. Please try registering again.' ) . '</p>';
        return $message;
    }
}

Bên trong chức năng Đăng nhập một lần, nếu người dùng có siêu dữ liệu 'email_not_verified', đừng đăng nhập chúng vào ứng dụng khách. (Điều này có thể xảy ra nếu người dùng được tạo thông qua biểu mẫu đăng ký được thêm bởi một plugin.)

$current_user = wp_get_current_user();
if ( get_user_meta( $current_user->ID, 'email_not_verified', true ) ) {
    echo( 'Invalid request.' ); // This needs to be changed to a redirect.
    exit;
}

Tôi cũng đã thêm một hộp kiểm để hiển thị và ghi đè trạng thái xác minh email của người dùng trên trang 'chỉnh sửa người dùng'.


Biên tập:

Móc vào validate_password_resethành động có lẽ không phải là cách tốt nhất để làm điều này. Nó được gọi trước khi mật khẩu được đặt lại, vì vậy email sẽ được xác minh ngay cả khi có lỗi trong quá trình đặt lại mật khẩu (ví dụ: nếu khóa hết hạn hoặc không hợp lệ.)

Một cách tiếp cận tốt hơn dường như là móc vào resetpass_formhành động và thêm một trường ẩn vào biểu mẫu đặt lại mật khẩu giữ giá trị của 'mail_key':

add_action( 'resetpass_form' 'sc_mail_key_field' );
function sc_mail_key_field() {

    if ( isset( $_REQUEST['mail_key'] ) ) { 

        $mail_key = sanitize_key( wp_unslash( $_REQUEST['mail_key'] ) );
        wp_nonce_field( 'verify_email', 'verify_email_nonce' );
        echo '<input type="hidden" name="mail_key" value="' . esc_attr( $mail_key ) . '" />';
    }
}

Sau đó có thể móc vào after_password_resethành động để xác minh khóa thư đã lưu so với $_POST['mail_key']giá trị.

Một plugin ví dụ có thể được tìm thấy ở đây: plugin xác minh địa chỉ email


1
Cảm ơn đã chia sẻ những gì làm việc cho bạn. PS: Tôi sẽ đề xuất tiền tố tùy chỉnh dữ liệu meta để tránh xung đột tên có thể xảy ra với các plugin khác và nên thêm exit;sau wp_redirect().
bạch dương

Cảm ơn, tôi đã chỉnh sửa mã ở đây để thêm exit;sau wp_redirect(). Trong mã tôi thực sự đang sử dụng, tôi không còn xóa người dùng nếu 'mail_key' của họ không khớp với khóa đã lưu. Thay vào đó, nếu các khóa không khớp, người dùng sẽ được tạo, nhưng có cờ 'email_not_verified'.
Simon Cossar

2

Tôi đã nhìn vào wp_usermetabảng và nhận thấy default_password_nagkhóa meta.

Tôi đã kiểm tra và điều này đã được giới thiệu trong # 9710 khoảng 7 năm trước.

Nếu người dùng có mật khẩu được tạo tự động thì giá trị của nó là 1 và cô ấy sẽ nhận được thông báo hiển thị trên màn hình bảng điều khiển.

Khi cô đăng ký lần đầu, default_password_naglà 1 và khi cô đặt lại mật khẩu, theo liên kết email, nó trở thành 0.

Bạn có thể xem xét thêm về điều này, nếu nó có thể được sử dụng trong thiết lập của bạn.

Nếu không, người ta có thể tạo một bộ đếm hoặc cờ tùy chỉnh và lưu trữ nó trong meta người dùng . Ví dụ, móc vào quá trình tạo người dùng và sau đó cập nhật nó khi người dùng đặt lại mật khẩu hoặc đăng nhập.


Vấn đề là plugin có thể cho phép đặt lại mật khẩu mà không cần người dùng trả lời email để đặt lại. WooC Commerce thực hiện việc này nếu bạn chọn 'bật đăng ký.' Có thể, có thể đủ tốt để biết rằng mật khẩu đã được đặt lại việc đặt lại đã được xử lý wp-login.php.
Simon Cossar

vâng, bạn đã đúng, các plugin có thể ảnh hưởng đến trạng thái của nó, ví dụ như thông qua các hình thức đăng nhập / đặt lại tùy chỉnh. Nhiều khả năng một bộ đếm / cờ tùy chỉnh có thể tốt hơn trong trường hợp đó. Trường hợp cực đoan sẽ là một plugin với việc tạo người dùng và đặt lại mật khẩu thông qua các truy vấn SQL tùy chỉnh ;-) @SimonCossar
birgire
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.