Deshabilitar o Redirigir WP-login.php
¿Existe alguna forma de evitar que los visitantes, ya estén logueados o no, accedan a misitio.com/wp-login.php
?
Tengo un formulario de login separado que es todo lo que necesitamos. Sé que puedo rediseñar el formulario generado por wp-login
pero preferiría no tener que lidiar con eso en absoluto. He probado varios filtros y hooks y no logro hacer que redirija. También intenté usar una redirección en .htaccess
y descubrí que funciona, pero entonces impide que mi formulario personalizado de login/logout funcione.
¿Alguna idea?

Después de encontrar esta pregunta y probar algunas de las respuestas, la siguiente es una versión "limpiada" de lo que estoy usando en un entorno de producción.
Esta versión no genera avisos/errores y también permite que los restablecimientos de contraseña funcionen:
// Enganchar la acción apropiada de WordPress
add_action('init', 'prevent_wp_login');
function prevent_wp_login() {
// WP rastrea la página actual - globalizar la variable para acceder a ella
global $pagenow;
// Verificar si $_GET['action'] está definido, y si es así, cargarlo en la variable $action
$action = (isset($_GET['action'])) ? $_GET['action'] : '';
// Verificar si estamos en la página de inicio de sesión, y asegurar que la acción no sea 'logout'
if( $pagenow == 'wp-login.php' && ( ! $action || ( $action && ! in_array($action, array('logout', 'lostpassword', 'rp', 'resetpass'))))) {
// Cargar la URL de la página de inicio
$page = get_bloginfo('url');
// Redirigir a la página de inicio
wp_redirect($page);
// Detener la ejecución para evitar que la página se cargue por cualquier razón
exit();
}
}

Esto parece evitar el acceso a WP-Login (bueno), pero el exit() final parece evitar que ocurra el login() real, lo cual no es lo que queremos. Queremos que las personas puedan iniciar sesión, simplemente que nunca vean la pantalla de WP-Login. Si ingresan una contraseña incorrecta, debería redirigir a nuestra página de inicio de sesión personalizada.

Editado y ahora funciona: debes verificar si $action está lleno antes de hacer in_array()

@Mike - ¿Estás seguro de que tu hook está funcionando? ¿Qué pasa si pones echo "AQUÍ";
dentro de la función? ¿Se muestra el texto?

@cale_b Sí, el hook funciona correctamente. El problema es que $_GET['action']
está vacío para mí. El formulario se envía a /wp-login.php
(sin ninguna variable GET en la URL) y al mirar el código fuente ni siquiera hay un campo llamado action
, por lo que incluso $_REQUEST['action']
está vacío.

@cale_b Parece que el código anterior se procesa después de que el login ya ha ocurrido. Si hago un exit;
(antes del wp_redirect
) y actualizo la página, no recibo una advertencia diciendo que estoy reenviando las variables post al servidor, lo que significa que el servidor ya ha realizado una redirección. Y si actualizo después de eso, ya estoy logeado.

@Mike - dos cosas: 1) esto no está destinado a evitar el inicio de sesión, está destinado a prevenir el acceso a wp-login.php (la página de inicio de sesión predeterminada de WP), y 2) he editado la respuesta y modificado ligeramente la lógica, lo que debería resolver el problema que describiste anteriormente.

Soy nuevo en php y también en WordPress. Mi pregunta es, en tu código, ¿dónde coloco el enlace para mi página personalizada de inicio de sesión/perfil?

Esto simplemente evita que cualquiera pueda iniciar sesión por mí, cuando se usa wp_login_form en una página personalizada. Nunca permitirá un inicio de sesión, ya sean credenciales válidas o no.

funciona para mí pero tengo problemas al cerrar sesión y no puedo entender por qué

Sí, esto bloquea mi formulario de inicio de sesión personalizado. Pero si hubiera una manera de verificar de forma confiable la variable de solicitud o quizás el referente? En otras palabras: esto podría ser un punto de partida. ¿Alguien más? Gracias de antemano ---JC

Ah sí, wp-login sí maneja el cierre de sesión. Lógico. Quizás este código con un plugin sea suficiente. Déjame ver qué más podemos usar porque odio usar wp-login.

Todo lo que creo necesario sería monitorear las variables de la solicitud cuando se carga wp-login. Simplemente no tengo una máquina que pueda hacer eso ahora mismo.

Estoy usando un plugin de Buddypress que redirige desde wp-login a una página de inicio de sesión personalizada. Quizás quieras mirar el código para ver cómo se hace. Se llama Branded Login for Buddypress, desarrollado por Brajesh Singh en (buddydev.com)

He estado usando el plugin de WordPress Rename wp-login.php desde hace bastante tiempo.
Te permite cambiar wp-login.php
a cualquier otra ruta. Tenía bots saturando mis páginas de inicio de sesión, y ahora no recibo ningún acceso.

WP-login gestiona el inicio de sesión, cierre de sesión, registro, restablecimiento y recuperación de contraseña. Asumiendo que deseas cambiar la página de inicio de sesión en el front-end. Puedes usar de forma segura el siguiente código:
function custom_login_page() {
$new_login_page_url = home_url( '/login/' ); // nueva página de inicio de sesión
global $pagenow;
if( $pagenow == "wp-login.php" && $_SERVER['REQUEST_URI'] == 'GET') {
wp_redirect($new_login_page_url);
exit;
}
}
if(!is_user_logged_in()){
add_action('init','custom_login_page');
}
Este fragmento de código hará:
- Redirigir a todos los visitantes del sitio a la nueva página de inicio de sesión.
- El cierre de sesión funcionará sin ningún problema
- En tu página personalizada de inicio de sesión tendrás que crear formularios personalizados para inicio de sesión, registro y restablecimiento de contraseña. Sin embargo, tus formularios personalizados pueden enviar datos de forma segura a wp-login.php ya que las solicitudes POST no son redirigidas.

home_url()
ya añade una barra inicial, así que no es necesaria. Además, $pagenow
es (a) una variable global que solo está presente en el área de administración (y quizás en el login) y (b) debería ser reemplazada con verificaciones de propiedades de get_current_screen()
.

// https://codex.wordpress.org/Plugin_API/Filter_Reference/login_url#Examples
add_filter('login_url', 'custom_login_url', 10, 3);
function custom_login_url($login_url, $redirect, $force_reauth) {
return home_url('/login/?redirect_to=' . $redirect);
}
Esto redirigirá a /login en lugar del feo formulario wp-login.

Si tu intención es proteger wp-login.php
para que extraños ni siquiera puedan verlo, la forma más simple y eficiente de hacerlo es requerir autorización (autenticación básica) para acceder a wp-login.php
.
En Apache, la autenticación se implementa mediante una combinación de htaccess y un archivo de contraseñas. La primera vez, dentro de una sesión del navegador, que alguien intente acceder a wp-login.php
se le pedirá que ingrese un nombre de usuario y contraseña (antes del inicio de sesión de WordPress).
Para simplificar las cosas, este nombre de usuario y contraseña pueden ser los mismos para cada persona a la que quieras dar acceso a wp-login.php
, ya que aún tendrán que ingresar sus credenciales de WordPress después de pasar exitosamente el primer cuadro de diálogo de autenticación.

Interesante. Supongo que el 'prompt' es el popup modal del navegador para ingresar credenciales. Creo que eso causaría confusión. Idealmente lo que quiero es que esa URL no haga -nada-... o quizás simplemente redirija a la página de inicio. Pero gracias por eso. ¡Se aprende algo nuevo cada día!

Lo que crees que estás haciendo es "seguridad a través de la oscuridad". Pero en realidad solo estás haciendo oscuridad, y eso es terrible. No lo uses. La autenticación es seguridad. Ocultar el punto de entrada es oscuridad. http://security.stackexchange.com/questions/32064/at-what-point-does-something-count-as-security-through-obscurity

En otras palabras, incluso SI cambias la ubicación de wp-login, aún necesitas usar autenticación: "¿Debería confiar en cambiar el servidor del puerto 22 al 2222 para mantener mi conexión segura? Absolutamente no. ¿Es malo cambiar mi servidor SSH al puerto 2222 mientras también uso una contraseña? No, de hecho esta es la mejor solución. Cambiar ('Ocultar') el puerto simplemente reducirá un montón de escaneos automáticos de exploits que buscan puertos normales. Ganamos una ventaja de seguridad a través de la oscuridad lo cual es bueno, pero no estamos dependiendo de la oscuridad. Si lo encuentran, aún necesitan descifrar la contraseña."

Reemplaza $pageid
con la página a la que deseas redirigir a los usuarios
/* Redirigir página de inicio de sesión */
function redirect_login_page(){
// Almacenar para verificar si esta página es igual a wp-login.php
$page_viewed = basename( $_SERVER['REQUEST_URI'] );
// enlace permanente a la página de inicio de sesión personalizada
$login_page = get_permalink($pageid);
if( $page_viewed == "wp-login.php" ) {
wp_redirect( $login_page );
exit();
}
}
add_action( 'init','redirect_login_page' );

<?php
/* Template Name: Plantilla de Registro */
if(is_user_logged_in()) { $user_id = get_current_user_id();$current_user = wp_get_current_user();$profile_url = get_author_posts_url($user_id);$edit_profile_url = get_edit_profile_url($user_id); ?>
<div class="regted">
Has iniciado sesión con el nombre de usuario <a href="<?php echo $profile_url ?>"><?php echo $current_user->display_name; ?></a> ¿Deseas <a href="<?php echo esc_url(wp_logout_url($current_url)); ?>">Salir</a> ?
</div>
<?php } else { ?>
<div class="register">
<?php $err = ''; $success = ''; global $wpdb, $PasswordHash, $current_user, $user_ID; if(isset($_POST['task']) && $_POST['task'] == 'register' ) { $pwd1 = $wpdb->escape(trim($_POST['pwd1']));
$pwd2 = $wpdb->escape(trim($_POST['pwd2']));
$email = $wpdb->escape(trim($_POST['email']));
$username = $wpdb->escape(trim($_POST['username']));
if( $email == "" || $pwd1 == "" || $pwd2 == "" || $username == "") {
$err = 'Por favor ingresa la contraseña en este campo';
} else if(!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$err = 'El email no es válido';
} else if(email_exists($email) ) {
$err = 'El email ya existe';
} else if($pwd1 <> $pwd2 ){
$err = 'La contraseña no coincide con la confirmación';
} else {
$user_id = wp_insert_user( array ('user_pass' => apply_filters('pre_user_user_pass', $pwd1), 'user_login' => apply_filters('pre_user_user_login', $username), 'user_email' => apply_filters('pre_user_user_email', $email), 'role' => 'subscriber' ) );
if( is_wp_error($user_id) ) {
$err = 'Error al crear el usuario.';
} else {
do_action('user_register', $user_id);
$success = 'Registro exitoso';
}
}
}
?>
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<!--mostrar mensaje de error/éxito-->
<div id="message">
<?php
if(! empty($err) ) :
echo ''.$err.'';
endif;
?>
<?php
if(! empty($success) ) :
$login_page = home_url( '/login' );
echo ''.$success. '<a href='.$login_page.'> Iniciar sesión</a>'.'';
endif;
?>
</div>
<div class="container">
<div id="loginbox" style="margin-top:100px;" class="mainbox col-md-6 col-md-offset-3 col-sm-8 col-sm-offset-2">
<div style="padding-bottom: 50px;" class="col-md-6 col-md-offset-4 col-sm-8 col-sm-offset-2"/><img src="#url.logo" alt="Logo del sitio" title="Logo"></div>
<form class="form-horizontal" method="post" role="form">
<div class="form-group">
<label class="control-label col-sm-3" for="username">Nombre de usuario:</label>
<div class="col-sm-9">
<input type="text" class="form-control" name="username" id="username" placeholder="Nombre de usuario">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3" for="email">Email:</label>
<div class="col-sm-9">
<input type="email" class="form-control" name="email" id="email" placeholder="Email">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3" for="pwd1">Contraseña</label>
<div class="col-sm-9">
<input type="password" class="form-control" name="pwd1" id="pwd1" placeholder="Ingresa tu contraseña">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3" for="pwd2">Repite la contraseña:</label>
<div class="col-sm-9">
<input type="password" class="form-control" name="pwd2" id="pwd2" placeholder="Repite la contraseña">
</div>
</div>
<?php wp_nonce_field( 'post_nonce', 'post_nonce_field' ); ?>
<div class="form-group">
<div class="col-sm-offset-3 col-sm-9" style="text-align:center;">
<button type="submit" class="btn btn-primary">Registrarse</button>
<input type="hidden" name="task" value="register" /><br/>
</div>
</div>
</form>
</div>
</div>
</div>
<?php
get_footer();
?>
<div class="message">
<?php
$login = (isset($_GET['login']) ) ? $_GET['login'] : 0;
if ( $login === "failed" ) {
echo '<strong>Error</strong> ¡Nombre de usuario o contraseña incorrectos!';
} elseif ( $login === "empty" ) {
echo '<strong>Error:</strong>El nombre de usuario o contraseña están vacíos.';
} elseif ( $login === "false" ) {
echo '<strong>ERROR:</strong> Salir';
}
?>
</div>
<?php } ?>
Ejemplo de mi página de inicio de sesión personalizada. Guardando login.php y colocando el código
add_action('init','wpse_login');
function wpse_login(){
global $pagenow;
if( 'wp-login.php' == $pagenow && !is_user_logged_in()) {
wp_redirect('http://tusitio.com/login.php');
exit();
}
}
en functions.php

¿Podrías editar tu pregunta y explicar por qué esta respuesta es mejor que las anteriores o qué es exactamente lo que estás haciendo? Las respuestas que solo contienen código generalmente no son bien recibidas sin algún tipo de explicación.

este código cambia wp-login.php por login.php con mi código personalizado basado en bootstrap. Puede prevenir bots automatizados o adivinanzas de la URL por defecto. Puedes cambiar <i>login</i> por la frase que quieras y nadie sabrá directamente la URL de acceso excepto tú.

add_action('check_admin_referer', 'logout_without_confirm', 10, 2); function logout_without_confirm($action, $result) { /* * Permite cerrar sesión sin confirmación / if ($action == "log-out" && !isset($_GET['_wpnonce'])) { $redirect_to = isset($_REQUEST['redirect_to']) ? $_REQUEST['redirect_to'] : 'https://tudominio.com'; $location = str_replace('&', '&', wp_logout_url($redirect_to)); header("Location: $location"); die; } }
