Разрешить вход на сайт WordPress только определенным ролям пользователей

В настоящее время у меня есть настройка сайта WP с уникальным плагином «мультисайта», установленным специально для обеспечения единой области администрирования продуктов WooCommerce, но с двумя разными интерфейсами, основанными на двух разных доменах, с отдельными темами.

Один из сайтов является «оптовым», а другой - «розничным». Оптовый сайт должен позволять совершать покупки только торговым клиентам. Проблема заключается в том, что оба сайта используют один домен и, следовательно, учетные записи пользователей.

Проблема: мне нужно убедиться, что пользователь, у которого нет роли пользователя trade_customer, пытается войти на оптовый сайт, роль проверяется, и пользователь выходит из системы, перенаправляется на страницу входа с уведомлением. Пока у меня в functions.php есть следующее:

function trade_customers_only() {
    function get_user_role() {
    global $current_user;

    $user_roles = $current_user->roles;
    $user_role = array_shift($user_roles);

    return $user_role;
}

$the_current_role = get_user_role();
echo $the_current_role;
    if( $the_current_role != 'administrator' ) {
       $logout_url = wp_login_url().'?mode=tradeonly';
       wp_destroy_current_session();
       wp_logout();
       wp_redirect( $logout_url, 302 );
       exit();
    }     
}
 add_action('wp_login', 'trade_customers_only');

// CUSTOM LOGIN MESSAGES
function my_login_message() {

    if( $_GET['mode'] == 'tradeonly' ){
        $message = '<p class="message"><b>You must be a Trade Customer to access this site.</b></p>';
        return $message;
    }

}
 add_filter('login_message', 'my_login_message');

Этот код в настоящее время: возвращает зарегистрированного пользователя на wp-login.php и добавляет примечание «Вы должны быть торговым клиентом ... и т. Д.». Однако после первой попытки входа в систему с любой ролью пользователя при каждой другой попытке входа выполняется такое же перенаправление и отображается сообщение. Мой код неверен или в базе данных или браузере есть файл cookie сеанса WP, вызывающий проблему, из-за которой WP думает, что я не использую учетную запись администратора?

В первый раз я попытался войти в систему с учетной записью администратора. это сработало и перешло на приборную панель. Следующая попытка была с ролевой учетной записью клиента. Перенаправление и примечание произошло. Следующая попытка с учетной записью администратора выполняла только перенаправление с примечанием, но без доступа к панели управления.


person Cuttsy27    schedule 04.05.2017    source источник


Ответы (3)


1) Измените функцию trade_customers_only:

function trade_customers_only($login, $user) {
    if( $user->roles && !in_array('administrator',$user->roles)) {
        $logout_url = wp_login_url().'?mode=tradeonly';
        wp_destroy_current_session();
        wp_logout();
        wp_redirect( $logout_url, 302 );
        exit();
    }
}

И исправьте свой призыв к действию:

add_action('wp_login', 'trade_customers_only',10,2);    

2) Другое решение - использовать фильтр аутентифицировать вместо действия wp_login. Разница в том, что вы проверяете роль пользователя до того, как пользователь устанавливает сеанс, поэтому вам не нужно его уничтожать.

add_filter('authenticate',function($user,$username) {
    if (!is_wp_error($user)) {
        $auth_user=get_user_by('login',$username);
        if ($auth_user && !in_array('administrator',$auth_user->roles)) {
            return new WP_Error('authentication_failed', '<p class="message"><b>You must be a Trade Customer to access Key Essentials. Are you looking for <a href="https://lovetillys.co.uk" title="Love Tillys">Love Tillys?</a></b></p>');
        }
    }
    return $user;
},100,2);
person Kulikov Sergey    schedule 04.05.2017

Мой новый полный код сейчас:

function trade_customers_only($login, $user) {
    if( $user->roles && !in_array('administrator',$user->roles)) {
        $logout_url = wp_login_url().'?mode=tradeonly';
        wp_destroy_current_session();
        wp_logout();
        wp_redirect( $logout_url, 302 );
        exit();
    }
}
 add_action('wp_login', 'trade_customers_only',10,2);

// CUSTOM LOGIN MESSAGES
function my_login_message() {

    if( $_GET['mode'] == 'tradeonly' ){
        $message = '<p class="message"><b>You must be a Trade Customer to access this site.</b></p>';
        return $message;
    }

}
 add_filter('login_message', 'my_login_message');

Этот код работает правильно. Однако, как заметил в своем ответе Куливов Сергей, использование фильтра аутентификации вместо действия wp_login лучше для того, что мне нужно. С использованием:

add_filter('authenticate',function($user,$username) {
    if (!is_wp_error($user)) {
        $auth_user=get_user_by('login',$username);
        if ($auth_user && !in_array('administrator',$auth_user->roles)) {
            return new WP_Error('authentication_failed', '<p class="message"><b>You must be a Trade Customer to access this site.</b></p>');
        }
    }
    return $user;
},100,2);

Он не только проверяет роль пользователя без входа в систему и создания сеанса, но и удерживает пользователя на своей текущей странице без перенаправления, и это здорово.

person Cuttsy27    schedule 05.05.2017

Я проверил, что приведенный ниже код работает правильно.

Нет необходимости запускать wp_destroy_current_session() или wp_logout(), просто вместо этого просто верните ошибку, и это прервет аутентификацию и покажет ваше сообщение об ошибке на странице входа.

Возможно, вам придется убедиться, что приоритет установлен последним (в данном случае 100), чтобы существующие фильтры wp_authenticate_username_password, wp_authenticate_email_password и wp_authenticate_spam_check выполняли свои функции и до того, как пользователь полностью войдет в систему, что вы затем откажете.

/* Only allow administrators to login */
add_filter( 'authenticate', 'my_admin_check', 100, 1 );

function my_admin_check( $user ) {
    // Make sure this is a real login attempt, without errors
    if ( !is_wp_error($user) ) {
        $user_role = $user->roles[0];
        // add or remove the roles you want to allow/disallow (can be a custom role or regular WordPress roles)
        if ( !in_array( $user_role, array( 'trade_customer' ) ) ){
            return new WP_Error( 'login_failed', __( "Only staff can use this login.", "mysite_domain" ) );
        } else {
            // allow the login
            return $user;   
        }
    } else {
        // We're just loading the login page, not running a login.
        return $user;       
    }
}   
person Dale Mugford    schedule 07.01.2019