14

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?

6
  • are you doing this for security reasons? why not implement auth for wp-login.php only?
    – Gaia
    May 20, 2013 at 18:13
  • I don't know what you mean by that. Please expand a bit. TIA.
    – jchwebdev
    May 21, 2013 at 18:38
  • WHY do you need a separate login form? for security reasons?
    – Gaia
    May 22, 2013 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, 2013 at 20:09
  • see answer provided.
    – Gaia
    May 22, 2013 at 21:47

9 Answers 9

26

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();
    }
}
11
  • 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, 2014 at 18:52
  • Edited it & it's now working: you have to check if $action is filled before doing in_array() Jul 21, 2014 at 21:45
  • This didn't work for me. I could still log in.
    – Mike
    Oct 3, 2015 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? Oct 3, 2015 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, 2015 at 22:24
11

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();
 }
}
6
  • working for me but im having log out issues & cant figure out why
    – Androliyah
    Aug 24, 2012 at 3:26
  • 7
    Because wp-login.php handles logging out as well. Aug 24, 2012 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, 2012 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, 2012 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, 2012 at 0:34
4

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();
 }
}
1
  • 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, 2014 at 19:11
3

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.

2

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.
2
  • 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, 2014 at 12:41
  • This works the best. Thank you
    – Herbert
    Mar 8 at 11:37
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.

2
  • hmmm interesting idea, but please explain how/why it works Jan 11, 2017 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, 2019 at 18: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.

4
  • 1
    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, 2013 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, 2013 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, 2013 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, 2013 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

2
  • 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, 2017 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, 2017 at 8:30

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