9

Is there a way to prevent visitors, whether logged in or not, from reaching mysite.com/wp-login.php?

I have a separate login form which is all we need. I know I can re-style the form generated by wp-login but I'd rather not have to deal with it at all. I've tried various filters and hooks and I can't seem to get it to redirect. I also tried using a .htaccess redirect and I found that this works, but then it prevents my custom login/logout form from working.

Ideas?

  • are you doing this for security reasons? why not implement auth for wp-login.php only? – Gaia May 20 '13 at 18:13
  • I don't know what you mean by that. Please expand a bit. TIA. – jchwebdev May 21 '13 at 18:38
  • WHY do you need a separate login form? for security reasons? – Gaia May 22 '13 at 1:05
  • We find that too many people these days are aware of the 'wp-login'. We'd rather not have that be quite so obvious. Can you just tell me what 'why not implement auth' means? TIA – jchwebdev May 22 '13 at 20:09
  • see answer provided. – Gaia May 22 '13 at 21:47
15

After finding this question, and testing a few of the answers, the below is a "cleaned up" version of what I am using in a production environment.

This version does not throw any notices / errors, and also allows for password resets to work:

// Hook the appropriate WordPress action
add_action('init', 'prevent_wp_login');

function prevent_wp_login() {
    // WP tracks the current page - global the variable to access it
    global $pagenow;
    // Check if a $_GET['action'] is set, and if so, load it into $action variable
    $action = (isset($_GET['action'])) ? $_GET['action'] : '';
    // Check if we're on the login page, and ensure the action is not 'logout'
    if( $pagenow == 'wp-login.php' && ( ! $action || ( $action && ! in_array($action, array('logout', 'lostpassword', 'rp', 'resetpass'))))) {
        // Load the home page url
        $page = get_bloginfo('url');
        // Redirect to the home page
        wp_redirect($page);
        // Stop execution to prevent the page loading for any reason
        exit();
    }
}
  • This seems to prevent WP-Login (good) but the final exit() seems to prevent the actual login() from occurring at all which is not what we want. We want people to be able to log in, just never see the WP-Login screen. If they enter an incorrect PW it should redirect to our custom login page. – jchwebdev Jul 15 '14 at 18:52
  • Edited it & it's now working: you have to check if $action is filled before doing in_array() – simonthesorcerer Jul 21 '14 at 21:45
  • This didn't work for me. I could still log in. – Mike Oct 3 '15 at 3:43
  • @Mike - Are you sure your hook is taking / working? What happens if you put echo "HERE"; inside the function? Does it echo? – cale_b Oct 3 '15 at 14:41
  • 1
    @cale_b Yes, the hook is working fine. The problem is that $_GET['action'] is empty for me. The form is posted to /wp-login.php (without any GET variables in the URL) and looking at the source there isn't even an in put named action, so even $_REQUEST['action'] is empty. – Mike Oct 3 '15 at 22:24
10

Try this in your theme's functions.php

add_action('init','custom_login');

function custom_login(){
 global $pagenow;
 if( 'wp-login.php' == $pagenow && !is_user_logged_in()) {
  wp_redirect('http://yoursite.com/');
  exit();
 }
}
  • working for me but im having log out issues & cant figure out why – Androliyah Aug 24 '12 at 3:26
  • 7
    Because wp-login.php handles logging out as well. – Brian Fegter Aug 24 '12 at 4:02
  • Yeah, this blocks my custom login form. But if there was a way to reliably check for the request var or perhaps referer? IOW: this might be a starting point. Anyone else? TIA ---JC – jchwebdev Aug 24 '12 at 7:15
  • Ah yes, wp-login does handle logging out. Lol. Thats logical. Perhaps this code with a plugin will suffice. Let me see what else we can use because I hate using wp-login. – Androliyah Aug 24 '12 at 19:12
  • All I think is necessary would be to monitor the request vars when wp-login is loaded. I just don't have a machine that can do that right now. – jchwebdev Aug 25 '12 at 0:34
3

Add a GET var for the logout action and it works fine.

add_action('init','custom_login');

function custom_login(){
 global $pagenow;
 if( 'wp-login.php' == $pagenow && $_GET['action']!="logout") {
  wp_redirect('http://YOURSITE.com/');
  exit();
 }
}
  • So far, this is the closest to what we want. If we remove the exit() and change the wp_redirect to our custom login page, it seems to do the job. – jchwebdev Jul 15 '14 at 19:11
2

I have been using the WordPress plugin Rename wp-login.php for quite sometime.

It lets you switch wp-login.php to any other path. I was having bots slam my login pages, and now I get zero hits.

1
// 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);
}

This will redirect to /login instead of the nasty wp-login form.

  • hmmm interesting idea, but please explain how/why it works – Mark Kaplun Jan 11 '17 at 15:25
  • This will not work. This filters requests for the login url via login_url(), it does not prevent someone from manually typing wp-login.php. – Matt Jul 4 at 18:41
0

WP-login handles login, logout, registeration, password reset and retrieval. Assuming you want to change the front-end login page. You can safely use the following code :

function custom_login_page() {
 $new_login_page_url = home_url( '/login/' ); // new login page
 global $pagenow;
 if( $pagenow == "wp-login.php" && $_SERVER['REQUEST_METHOD'] == 'GET') {
    wp_redirect($new_login_page_url);
    exit;
 }
}

if(!is_user_logged_in()){
 add_action('init','custom_login_page');
}

This code snippet will:

  1. Redirect all website visitors to new login page.
  2. Logout will work without any problem
  3. On your custom login page you will have to create custom login , registration and password reset forms, However your custom forms can safely post data to wp-login.php as post requests are not redirected.
  • 1
    home_url() already adds a leading slash, so no need for that. Also $pagenow is (a) a global that is only present on admin (and maybe the login) and (b) should be replaced with get_current_screen() property checks. – kaiser Oct 29 '14 at 12:41
0

If your intention is to protect wp-login.php from strangers even being able to see it, the simplest efficient way to do so is to require authorization (basic auth) to access wp-login.php.

In Apache, auth is implemented via a combination of htaccess and a password file. The first time, within a browser session, that anyone tries to access wp-login.php they will be prompted to enter an username and password (before the wordpress login).

To simplify things, this username and password can be the same for every person you want to give access to wp-login.php, as they still have to enter their wordpress login after successfully getting past the first the auth dialog box.

  • Interesting. I'm assuming the 'prompt' is the browser's modal popup for entering credentials. I think that would cause confusion. Ideally what I want is for that URL to do -nothing-... or perhaps just redirect to the home page. But thanks for that. Learn something new every day! – jchwebdev May 27 '13 at 2:57
  • What you are think you are doing is "security thru obscurity". But in reality you are only doing obscurity, and that is terrible. Do not use it. Auth is security. Hiding the entrance point is obscurity. security.stackexchange.com/questions/32064/… – Gaia May 27 '13 at 11:50
  • 1
    In other words, even IF you change the location of wp-login, you still need to use auth: "Should I rely on changing the server from 22 to port 2222 to keep my connection safe? Absolutely not. Is it bad to change my SSH server to port 2222 while also using a password? No, if anything this is the best solution. Changing ("Obscuring") the port will simply cut down on a heap of automatic exploit scanners searching normal ports. We gain a security advantage through obscurity which is good, but we are not counting on the obscurity. If they found it they still need to crack the password." – Gaia May 27 '13 at 12:41
  • Thanks for that. I learned a lot. Not what I was looking for, but still... very helpful. Best ---JC – jchwebdev May 31 '13 at 3:51
0

Replace $pageid with the page you want users to be redirected to

/* Redirect log in page */
function redirect_login_page(){
  // Store for checking if this page equals wp-login.php
   $page_viewed = basename( $_SERVER['REQUEST_URI'] );

  // permalink to the custom login page
  $login_page  = get_permalink($pageid);

  if( $page_viewed == "wp-login.php" ) {
    wp_redirect( $login_page );
    exit();
  }
}

add_action( 'init','redirect_login_page' );
0
<?php
/* Template Name: Register Template */
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">
    You're login with nickname <a href="<?php echo $profile_url ?>"><?php echo $current_user->display_name; ?></a> Are you want to <a href="<?php echo esc_url(wp_logout_url($current_url)); ?>">Exit</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 = 'Please enter password in this field';
        } else if(!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            $err = 'Email is invalid';
        } else if(email_exists($email) ) {
            $err = 'Email is existed';
        } else if($pwd1 <> $pwd2 ){
            $err = 'Password does not match the confirm password';
        } 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 on user creation.';
            } else {
                do_action('user_register', $user_id);
                $success = 'Registered Successfully';
            }
        }
    }
    ?>
  <link  rel="stylesheet" type="text/css"  href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<!--display error/success message-->
<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.'> Login</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"></div>
    <form class="form-horizontal" method="post" role="form">
<div class="form-group">
    <label class="control-label  col-sm-3" for="username">Username:</label>
    <div class="col-sm-9">
    <input type="text" class="form-control" name="username" id="username" placeholder="Username">
    </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">Password</label>
    <div class="col-sm-9">
        <input type="password" class="form-control" name="pwd1" id="pwd1" placeholder="Enter your password">
    </div>
</div>
<div class="form-group">
    <label class="control-label col-sm-3" for="pwd2">Retype password:</label>
    <div class="col-sm-9">
        <input type="password" class="form-control" name="pwd2" id="pwd2" placeholder="Retype password">
    </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">Register</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> Wrong username or password!';
        } elseif ( $login === "empty" ) {
                echo '<strong>Error:</strong>Username or password is blank field.';
        } elseif ( $login === "false" ) {
                echo '<strong>ERROR:</strong> Exit';
        }
    ?>
</div>
<?php } ?>

Example my custom login page. Saving login.php and put code

add_action('init','wpse_login');

function wpse_login(){
 global $pagenow;
 if( 'wp-login.php' == $pagenow && !is_user_logged_in()) {
  wp_redirect('http://yoursite.com/login.php');
  exit();
 }
}

in functions.php

  • Could you please edit your question and explain why this answer is better than previous answers or what exactly you're doing what you're doing. Code only answers are usually frowned upon without some sort of explanation. – Howdy_McGee Aug 18 '17 at 4:07
  • this code switch wp-login.php to login.php with my custom code based on bootstrap It can prevent auto bot or guess default url. use can change <i>login</i> to phrase what you want.and no one know directly login url excerp you. – Rei Aug 20 '17 at 8:30

protected by Community Oct 4 '15 at 20:40

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.