All standard login / registration action are done using 'wp-login.php'
file.
The standard comments are saved using 'wp-comments-post.php'
file.
Blocking this 2 files you block standard flow for comments, login, registration and password recover.
Very early in its bootstrap WordPress save a global variable $pagenow
that contain the name of the file being loaded. You can use that variable to block the flow.
Blocking comments will be very simple, because you want block it for all.
First let’s write a function that ends the request, send an http header 403 and outuput a message. That can be done using wp_die
function restrict_standard_flow( $not_allowed = 'Action' ) {
$args = array( 'response' => 403 ); // set response to 403
$msg = $not_allowed . ' not allowed';
if ( restrict_used_method() === 'GET' ) {
$args['back_link'] = TRUE; // show a back link if request send via GET
};
wp_die( $msg, $msg, $args );
}
restrict_used_method()
is a function that return the current method used:
function restrict_used_method() {
$method = filter_input( INPUT_SERVER, 'REQUEST_METHOD', FILTER_SANITIZE_STRING );
return strtoupper( $method ) === 'GET' ? 'GET' : 'POST';
}
This function prevent unexpected behavior if methods are not POST or GET.
At this point, we can use $pagenow
variable to end the request if it is 'wp-comments-post.php'
and run a function if it is 'wp-login.php'
.
add_action( 'plugins_loaded', function() {
global $pagenow;
if ( $pagenow === 'wp-login.php' ) {
restrict_standard_login_flow();
} elseif ( $pagenow === 'wp-comments-post.php' ) {
restrict_standard_flow( 'Standard comment flow' );
}
});
So the standard comment flow is blocked, we have to write restrict_standard_login_flow()
function.
I think that an easy way to implement password protection is to allow inserting the password as url variable. In that case we have to assure that a password in the url is also included in login form, to pass it when it’s submitted.
We can do this using 'login_form'
action hooks:
add_action( 'login_form', 'embed_pwd_in_form' );
function embed_pwd_in_form() {
if ( ! is_super_admin() && defined('MY_SECRET') && MY_SECRET ) {
$type = restrict_used_method() === 'GET' ? INPUT_GET : INPUT_POST;
$pwd = filter_input( $type, 'mypwd', FILTER_SANITIZE_STRING );
if ( ! empty( $pwd ) ) {
echo "<input type="hidden" name="mypwd" value="" . md5($pwd). "" />";
wp_nonce_field( 'pwd_nonce', 'pwd_n' );
}
}
}
So we look at url and if the url variable 'mypwd'
put it md5-ed in a hidden field, along another hidden nonce field.
The password that you will put in the url, must be compared to something… a simple way is use a constant:
Open your wp-config.php
and just before
/* That's all, stop editing! Happy blogging. */
put
define( 'MY_SECRET', 'your-password-here' );
Of course, replace ‘your-password-here’ with your real password.
Now we can write the restrict_standard_login_flow()
function that compare the password in the url to the constant and also check the nonce if current http method is POST:
function restrict_standard_login_flow() {
// if the current user is not already logged as super admin
// and a constant 'MY_SECRET' is defined
if ( ! is_super_admin() && defined('MY_SECRET') && MY_SECRET ) {
$type = INPUT_GET;
$not_allowed = FALSE;
if ( restrict_used_method() === 'POST' ) {
// sent via form, check a nonce
$type = INPUT_POST;
$nonce = filter_input( $type, 'pwd_n', FILTER_SANITIZE_STRING );
if ( empty($nonce) || ! wp_verify_nonce( $nonce, 'pwd_nonce' ) ) {
$not_allowed = 'Nonce';
}
}
if ( $not_allowed === FALSE ) { // nonce is valid, check password
$pwd = filter_input( $type, 'mypwd', FILTER_SANITIZE_STRING );
// if the password is sent via url, md5 it, like in form
if ( restrict_used_method() === 'GET' ) $pwd = md5($pwd);
// if password is not valid
if ( $pwd === md5(MY_SECRET) ) {
$not_allowed = 'Standard login flow';
}
}
if ( $not_allowed === FALSE ) { // if not allowed exit
restrict_standard_flow( $not_allowed );
}
}
}
Please see inline comments for additional details.
Now, to use standard login flow you have to use an url like
http://www.example.com/wp-login.php?mypwd=your-password-here
If you don’t set the password the request will be refused.
Please note that code here allow only login form, lost/reset password form are not allowed, so or you extend the code to allow them or you use your custom flow for those tasks.
As alternative, never forget the password 😉
Registeri form is also not allowed, because you want only you are able to use standard flow, and you are already registered.