1

I'm trying to password protect content in a custom page template, however when i enter the password i assigned in the backend, it doesn't authenticate, instead just reloads the page upon submission. I know the code below isn't great, but please try to disregard this - I just need help getting the password authentication to work properly.

It also seemingly doesn't check to see if the specific page is actually password protected, but instead shows the password protection form regardless of whether the page is public or password protected, so i guess here-in lies the issue.

<div class="container">
    <?php if (post_password_required()) { ?>
    <div class="trips">
        <div class="homewrap">

        <?php
            // get all the categories from the database
            $args = array('orderby' => 'id', 'order' => 'desc');
            $cats = get_categories($args);
            $i = 0;
            $n = 0;

                // loop through the categries
                foreach ($cats as $cat) {

                    // setup the cateogory ID
                    $cat_id = $cat->term_id;
                    // Make a header for the cateogry
                    $string = $cat->name;
                    $nstring = strtolower(str_replace(" ", "-", $string));
                    echo "<a href='/" .$nstring. "'><div class='where'><h2 class='place'>".$cat->name."</h2></a>";
                    // create a custom wordpress query
                    query_posts("cat=$cat_id&posts_per_page=100");
                    // start the wordpress loop!
                    if (have_posts()) : while (have_posts()) : the_post(); ?>

                        <?php // create our link now that the post is setup 

                            $i++;
                            if ($i >= 2) {
                                echo '<div class="thing">';
                            }

                        ?>

                        <div class="location"><a href="<?php the_permalink();?>"><?php the_title(); ?></a></div>
                        <?php 

                            $thumbnail = get_the_post_thumbnail();
                            $url = get_the_permalink();
                            $description = get_post_meta( get_the_ID(), 'description', true );

                            echo '<div class="pictures">';
                            echo '<div class="featured-thumb"><a href="' .$url. '">' .$thumbnail. '</a></div>';
                                if (class_exists('Dynamic_Featured_Image') ) {
                                    global $dynamic_featured_image;
                                    $featured_images = $dynamic_featured_image->get_featured_images( $postId );
                                    $number = count($featured_images);

                                    for ($i = 0; $i <= 1; $i++) {
                                        echo '<div class="featured-thumb"><a href="' .$url. '"><img src="' .$featured_images[$i]['full']. '"></a></div>';
                                    }
                                }

                            echo '</div><!-- pictures -->'; 
                            echo '<div class="description">' .$description. '</div>';

                            if ($i >= 2) {
                                echo '</div><!-- .thing -->';
                            }

                        ?>

                    <?php endwhile; endif; // done our wordpress loop. Will start again for each category ?>
                <?php } // done the foreach statement ?> 
        </div>   
        </div><!-- .container -->
    </div><!-- .homewrap -->
</div><!-- .trips -->
<?php } else { echo get_the_password_form(); } ?>

<?php

get_footer();
  • Try it with a different browser and make sure that Cookies are allowed on that domain (in your browser or your OS in general). Does that make a difference? (Hint: It should). – kaiser Dec 16 '14 at 0:16
2

Try reversing the condition :

if(post_password_required( )):
    echo get_the_password_form();
else:
    // if password not required or password cookie is present
    // your protected content here
endif;

See codex

Hope that helps.

  • Thanks, but the password protection is actually working as it should (it's asking me for a password) - but when i enter the password, it doesn't work (when i enter the password i set). – Nikki Mather Dec 15 '14 at 22:35
  • What happens when you enter password ? – Céline Garel Dec 15 '14 at 22:49
  • The same thing, nothing. The form still displays. – Nikki Mather Dec 16 '14 at 10:54
  • This answer worked perfectly for me, and it avoids setting any global vars or calling that header function. – Nubtacular Jul 31 '18 at 4:02
2

Basic how and why

Extending on my blog post about that topic:

When you enter a password into a form built by get_the_password_form(), the form targets ~/wp-login.php with a query argument named postpass which is the $action the login file uses to switch. There the PasswordHash class gets into use and a cookie gets set [...]

When does it happen?

The post_password_required() function returns a boolean true if:

  1. ! empty( $post->post_password )
  2. ! isset( $_COOKIE['wp-postpass_' . COOKIEHASH] )
  3. The form(/user) input hash does not match

    require_once ABSPATH . WPINC . '/class-phpass.php';
    $hasher = new PasswordHash( 8, true );
    $hasher->CheckPassword( $post->post_password, $hash );
    
  4. The saved Cookie value does not match

    $hash = wp_unslash( $_COOKIE[ 'wp-postpass_' . COOKIEHASH ] );
    0 !== strpos( $hash, '$P$B' )
    

In all that cases, the true value will - or depending on your template: should - return the post password form using get_the_password_form(). Protip: You can alter it's UI via the apply_filters( 'the_password_form', $output ); filter and yes, it's plain HTML as string value.

Minetraps for children

Keep in mind that attachments and child pages (in hierarchical post types) will not be password protected. That needs separate consideration and template code (simply check if the parent is password protected if you need to protect children by parents).

API considerations / No brainers

There are actually some core API functions that will output something by themselves (list maybe not complete):

  • get_the_content() -> Post Password form with get_the_password_form()
  • the_content() ... the same
  • get_the_excerpt(): __( 'There is no excerpt because this is a protected post.' );
  • the_excerpt() ... the same
  • get_post_class() will add the 'post-password-required' class to the output list

For all other cases you probably should code up your own logic.

Possible stoppers: User denies Cookie usage

Check if the user allows Cookies. If they aren't allowed, you have a problem. That actually is quite easy as WP comes with a test cookie per default. See wp-login.php for an example. (The TEST_COOKIE constant is defined in wp-includes/default-constants.php as define('TEST_COOKIE', 'wordpress_test_cookie');):

if ( SITECOOKIEPATH != COOKIEPATH )
        setcookie( TEST_COOKIE, 'WP Cookie check', 0, SITECOOKIEPATH, COOKIE_DOMAIN, $secure );

So the value to check against is 'WP Cookie check'. And the check that core itself does is:

if ( empty( $_COOKIE[ TEST_COOKIE ] ) )

which you could easily replicate in a callback on template_redirect - or just in your template. Then present the user a message that it won't work without Cookies.

If this isn't the problem, then you will have to dig deeper and update the question with additional info.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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