Los perfiles de usuario en WordPress están todos en el área de administración, incluso de aquellos que nada tienen que ver con la administración de la web. A priori no representa ningún peligro de seguridad como algunos pueden sostener, para mi lo más importante es que la experiencia del usuario puede verse truncada.

Por ejemplo, una tienda online puede requerir la creación de una cuenta de usuario desde la que gestionar la información de envío o de facturación. Es mucho mejor que el usuario permanezca en el frontend con una experiencia integrada, no necesita acceder al backend para nada dónde además se encontrará con un aspecto totalmente diferente al de la tienda dónde estaba comprando. Por eso es frecuente que se solicite permitir el acceso al área de administración sólo a determinados usuarios, sobre todo a administradores. Y eso es lo que vamos a ver en este tutorial.

Hay que tener en cuenta que las solicitudes Ajax en WordPress desde el frontend también necesitan acceso al área de administración (wp-admin/admin-ajax.php) y no deben ser bloqueadas.

Restricción en base a la capacidad manage_options

La capacidad manage_options (manejo de opciones del sitio) viene por defecto asociada a los usuarios “administrator”. Con la función current_user_can() podemos comprobar si un usuario que está intentando acceder a alguna zona de wp-admin tiene esta capacidad y si no la tiene redirigirlo al frontend.

add_action( 'admin_init', 'admin_area_for_manage_options_only');
function admin_area_for_manage_options_only() {

      if( defined('DOING_AJAX') && DOING_AJAX ) {
            // Permitir solicitudes a wp-admin/admin-ajax.php
            return;
      }

      if( ! current_user_can( "manage_options" ) ) {
           // Redireccionar a la página principal del sitio
           // si el usuario no tiene la capacidad "manage_options"
           wp_redirect( esc_url_raw( get_site_url() ) );
           exit();
      }

}

Restricción en base al rol administrator

Para comprobar si el usuario actual es “administrator” se ha de obtener la información sobre los roles asignados y comprobar si entre ellos está el de “administrator”:

add_action( 'admin_init', 'admin_area_for_admins_only');
function admin_area_for_admins_only() {

      if( defined('DOING_AJAX') && DOING_AJAX ) {
            // Permitir solicitudes a wp-admin/admin-ajax.php
            return;
      }

      $user = wp_get_current_user();

      if( empty( $user ) || ! in_array( "administrator", (array) $user->roles ) ) {
           // Redireccionar a la página principal del sitio
           // si el usuario no tiene el rol "administrator" asignado
           wp_redirect( esc_url_raw( get_site_url() ) );
           exit();
      }

}

Esta fue mi respuesta a un pregunta en WPSE que puedes votar si crees que es buena y de paso me das unos puntillos ;).

En lugar de redirigir al usuario al home de la web puedes querer redirigirlo a otra URL del frontend, por ejemplo, si usas bbPress puedes estar interesado en redirigir al perfil del usuario en bbPress. Sustituye wp_redirect( esc_url_raw( get_site_url() ) ) por:

wp_redirect( esc_url_raw( bbp_user_profile_url( bbp_get_current_user_id() ) ) );

¿Qué método elegir?

En WordPress existen roles y capacidades (capabilities). A cada rol se le asignan unas determinadas capacidades y es frecuente que para referirse a los usuarios con rol “administrator” se recurra a comprobar si el usuario tiene capacidad para manejar las opciones del sitio (manage_options). Y esto es lo que se hace en muchos tutoriales sobre permitir el acceso a la administración de WordPress sólo a los administradores.

Pero yo no estoy de acuerdo con esos tutoriales. O al menos no como solución para todos los casos. Si bien es cierto que la capacidad manage_options viene por defecto asignada al rol “administrator”, las capacidades de cada rol pueden ser alteradas a través de plugins. Por ejemplo, se podría asignar la capacidad manage_options al rol “editor”, o se podría crear un rol “webmaster” y asignarle también la capacidad manage_options. Por eso, si se quiere permitir el acceso a la administración sólo a administradores, o a cualquier otro rol o tipo de usuario, debe comprobarse el rol y no una capacidad.

A pesar de todo esto, yo suelo elegir comprobar la capacidad manage_options en lugar del rol “administrator” aunque pueda parecer contradictorio. ¿Por qué? Sencillamente por que no tiene sentido que un rol tenga capacidad de manage_options pero no tenga acceso a wp-admin pues es en la administración dónde las funciones asociadas a esa capacidad pueden ser ejecutadas.

Nota: es muy común ver como se comprueban roles con la función current_user_can. Este uso se debe evitar pues, según la documentación oficial de WordPress, no se garantiza que funcione correctamente. Además, este “fallo” no ha sido aceptado como bug para ser solucionado pues la función current_user_can no fue diseñada para este fin.

Más información

Además de las soluciones expuestas aquí, existen otras opciones para restringir el acceso a wp-admin, por ejemplo proteger con contraseña el directorio wp-admin a través de .htaccess. En este caso la restricción es manejada a nivel de servidor, no por WordPress, y si se hace una solicitud a wp-admin no se ejecuta ni una línea de código sin que se introduzca el usuario y contraseña configurado en el servidor y además se requerirá después la identificación del usuario en WordPress.

  • Guilherme Felicissimo

    thanks man!

  • Miguel

    hola amigo, al un autor hacer login y entrar al panel de administracion en mi web se encuentra con lo siguiente: Escritorio, Entradas,Medios, Comentarios,Contacto, Herramientas, Perfil como hago para que los usuarios con rango de autor solo puedan ver “Entradas” y “Perfil” es ¿posible?

  • donde se pega el código

    • En un plugin, ¿dónde si no?

      En functions.php del theme activo también funcionará pero es indudable que este código es territorio de plugins.