使用电子邮件和确认链接进行WordPress身份验证

时间:2017-12-15 14:40:09

标签: php wordpress authentication

我试图改变Wordpress身份验证的行为。我有专门为我公司成员的网站,我只希望他们访问它,而无需管理大量不同的用户帐户,验证它们等。

我的想法是隐藏未登录用户的网站并向他们显示登录表单,在那里,只显示电子邮件字段(做得非常好,只是创建了带有wp-login.php副本的自定义页面并进行了重定向未登录的观众,我认为这可能是完全自定义登录页面的最佳方式。)

现在我必须改变身份验证功能的行为方式,但完全不知道如何启动它,据我所知,我必须为许多功能制作许多不同的过滤器。我完全停电了,不能

以下是注册/登录的过程:

  • (已完成)用户进入该页面,如果未记录,他将看到只有电子邮件字段和提交按钮的登录表单

  • 他将输入他的电子邮件并点击提交(这里我必须摆脱"没有密码"错误信息)

  • 如果允许电子邮件在域中(将从选项中提供允许的域数组),用户将收到一封电子邮件,其中包含要继续的链接

  • 点击链接后,用户进入页面并通过&#34进行身份验证;记住我"设置,而无需设置任何密码等(在此之前,如果没有用户这样的电子邮件,WP将创建一个用户名包含@之前的字符和随机强密码)

因为整个身份验证系统有很多变化,所以我无法理解它。我从哪里开始修改必填字段?我应该使用哪种挂钩?

PS:我不想创建新的身份验证系统,我需要依赖修改WP功能。

搞定了!

下面的部分解决方案

已经开始工作了。 我最终创建了一个wp-login页面的副本,并将所有未登录的用户重定向到它,页面位于/ start /下。 我的主题中的page-start.php基本上是wp-login的副本,几乎没有调整(无法记住所有tbh)。

我没有提及登录表单修改和样式更改,只提及脚本。

page-start.php(wp-login.php的副本)

首先,重定向已经登录用户到root(在文件的开头):

session_start();
if(is_user_logged_in()) {

        wp_redirect( '/' );
        exit;
}   

接下来,我已经更改了部分代码来处理秘密登录字符串,如果它匹配并且还没有过期(重要),它将登录新用户。

    if(isset($_GET['key'])) {
        $_SESSION['let_me_in_key'] = $_GET['key'];
        session_write_close();
        wp_redirect(home_url('/start/')); 
        exit();
    }
    if(isset($_SESSION['let_me_in_key'])) {
        global $wpdb;
        $let_me_in_key = $_SESSION['let_me_in_key'];
        $_SESSION['let_me_in_key'] = NULL;
        unset($_SESSION['let_me_in_key']);
        $sha = $let_me_in_key;
        $res = $wpdb->get_results("SELECT * FROM {$wpdb->users} WHERE user_activation_key LIKE '%{$sha}'",ARRAY_A);
        if (!isset($res[0])) {
            $errors ->add('invalid_key', 'Nieprawidłowy klucz aktywacyjny, zaloguj się ponownie aby otrzymać nowy klucz w wiadomości email.');
        } else {
            $db_key = explode(':',($res[0]['user_activation_key']));
            $minutes = (time()-$db_key[0]);
            if($minutes > 60*60) {
                $errors ->add('expired_key', 'Klucz aktywacyjny wygasł, zaloguj się ponownie aby otrzymać nowy klucz w wiadomości email.');
            } else {
                $user = get_userdata($res[0]['ID']);
                $wpdb->query("UPDATE {$wpdb->users} SET user_activation_key = '' WHERE ID = {$user->ID}");
                clean_user_cache($user->ID);
                wp_clear_auth_cookie();
                wp_set_current_user($user->ID);
                wp_set_auth_cookie($user->ID, true, true);
                update_user_caches($user);
                wp_redirect(home_url());

            }
        }
    }

这是在这部分之后添加的:

if ( $interim_login ) {
        if ( ! $errors->get_error_code() )
            $errors->add( 'expired', __( 'Your session has expired. Please log in to continue where you left off.' ), 'message' );
    } else {

的functions.php

现在我已经添加了处理自定义登录的功能。 首先它会删除wp_authenticate_username_password,然后它会添加自己的身份验证功能 它会检查电子邮件是否有效,然后是否是允许的域之一(我使用的是ACF,因此我的自定义数据由get_field()访问)。 如果一切正确,脚本将使用wp_generate_password生成密码(密码将不重要,因为用户不必使用它,但它更好创建比123qwe更安全的东西:D)并创建用户剥离@并仅保留域部分中的字母数字字符(我不会在@之前剥离部分中的任何特殊字符,但是你可以)。

remove_filter('authenticate', 'wp_authenticate_username_password', 20);
add_filter('authenticate', function($user, $email, $password){
        $email = strtolower($_POST['log']);
        $allowed_domains = array_map('trim',array_filter(explode(PHP_EOL, get_field('domeny','options'))));
        $domain = explode("@", $email);
        if($_POST['log']) {
            if(!filter_var($email, FILTER_VALIDATE_EMAIL) ){ //Invalid Email
                $error = new WP_Error();
                $error->add('invalid_username', 'Błędny adres email.');
                return $error;
            }
            else if(!in_array($domain[1],$allowed_domains)){ //Invalid Email
                $error = new WP_Error();
                $error->add('invalid_username', 'Niedozwolony adres email. Czy na pewno używasz adresu służbowego?');
                return $error;
            }
        } else return $user;
        //Check if user exists in WordPress database
        $user = get_user_by('email', $email);
            if(!$user){ 
                $pass = wp_generate_password( $length=12, $include_standard_special_chars=false );
                $user_id = wp_create_user( $domain[0].preg_replace("/[^a-zA-Z0-9_]+/", "",$domain[1]), $pass, $email );
                wp_update_user( array( 'ID' => $user_id, 'display_name' => $email ) );
                $user = get_userdata($user_id);
            } else {
                $user_id = $user->ID;
            }

            if(send_activation_link($email,$user_id)) {
                $error = new WP_Error();
                $error->add('confirm', 'Na podany email został wysłany link z potwierdzeniem logowania. Kliknij w link z wiadomości aby przejść dalej.', 'message');
            }
                return $error;
}, 20, 3);

我还必须更改wp_authenticate才能获得用户名:

add_action( 'wp_authenticate', 'email_address_login' );
function email_address_login( &$username, &$password )
{
    $user = get_user_by( 'email', $username );

    if( !empty( $user->user_login ) )
    {
        $username = $user->user_login;
    }
}

除此之外,我还必须创建一个生成密钥的函数,并发送激活链接:

function send_activation_link($email,$user_id){

add_filter( 'wp_mail_content_type', 'wpdocs_set_html_mail_content_type' );

    global $wpdb, $wp_hasher;
    $salt = wp_generate_password(20,false); // 20 character "random" string
    $sha = sha1($salt . $email . uniqid(time(), true));
    //$a_z = 'abcdefghijklmnopqrstuvwxyz';
    $key_saved = $wpdb->update( $wpdb->users, array( 'user_activation_key' => time().':'.$sha ), array( 'ID' => $user_id ) );
    if ( false === $key_saved ) {
        return new WP_Error( 'no_password_key_update', __( 'Could not save password reset key to database.' ) );
    }
    /* send mail here */

remove_filter( 'wp_mail_content_type', 'wpdocs_set_html_mail_content_type' );
}

1 个答案:

答案 0 :(得分:0)

  • 他将输入电子邮件并点击“提交”(在这里我必须摆脱“否 密码”错误消息)

  • 如果电子邮件位于允许的域中(允许的域数组将为 由选项提供),用户将收到一封电子邮件,其中包含要链接到 继续

这两个应该结合使用-如果存在数组中的电子邮件,请使用wp_insert_user和自动生成的密码。

  • 单击链接后,用户进入页面并通过身份验证 使用“记住我”设置,而无需设置任何密码 等等(在此之前,如果没有用户使用该电子邮件,WP将 创建一个用户名,用户名包含@之前的字符,然后随机 强密码)

这可能是一些随机数(请参阅wp_nonce_field)字段,该字段会在返回时进行身份验证。

这是一个漫长的问题,所以它并不是真正的“一个答案”,但是您更适合设置自己的表单并使用Ajax或类似的东西。