WordPressの投稿や固定ページには、もともとパスワード保護機能があります。ただこれはパスワードがページ全体に作用してしまうため、途中までは読めるようにしておいてそこから先はパスワードが必要、とか、途中の一部だけをパスワード保護するといったことができません。
そこで今回は、プラグインなしで投稿や固定ページの一部をパスワードで保護するようなコンテンツが作れるようになる方法を2通り紹介します。
なお最初にお断りしておきますが、本ページの方法は作ってみたというもので、他にいい方法があるかも知れませんし、動作やセキュリティ的に何か問題があるかも知れませんので、安全性を考えるなら以下のプラグインを使うのが妥当かも知れません、
本ページ掲載のコードを使用するときは
本ページで掲載しているコードは、以下に了承した上で使用ください
- コードは商用・非商用問わず自由に使っていただいて構いませんが、コード追加による不具合やトラブルが発生しても当方では一切責任を負いません
- コードは有効化しているテーマのfunctions.php、style.cssなどへ追加することで機能します。それらのファイルへの変更を行うことに不安のある方は使用しないでください
- コードは本ページの公開日時点で私の環境において動作したものです。WordPressバージョン他環境の違いによって動作しないことがあります
- コードは、セキュリティ、コードの正確さなどにおいて完全なものではありません。中には紹介するコードを簡略化するために省略している部分があるものもありますので、ご自身でコードを十分に検証し、必要な部分の編集を行った上で使用するようにしてください
- 掲載しているのは参考コードです。自身の環境に合わせるための編集はご自身で対応いただく必要があります(コメント欄等から質問いただいても基本回答は致しません)
- 掲載しているコードの転載を禁じます(SNSで紹介いただいたり、本ページへのリンクを張っていただくことは大歓迎です)
どちらの方法でも難しかったこと
ここから2つの方法を紹介していきます。それぞれに一長一短ありますのでやりやすい方法で行うといいと思いますが、どちらの方法でも、複数の保護コンテンツを1つの投稿または固定ページ内に設置した場合に以下のようなことが発生します。
- 同じパスワードを持つものが1つの認証で同時に展開される
- 別のパスワードを持つものが複数ある場合、一方を認証すると、他方は非認証の状態になってしまう
いろいろと解消できないかと試行錯誤したものの解消はできませんでしたので、あくまでも1つの投稿や固定ページ内に、同じパスワードを持つ複数の保護コンテンツを入れる、または、1つの保護コンテンツを入れるという使い方に限定したほうがいいでしょう。
1.パスワード保護コンテンツ用のカスタム投稿タイプを作る方法
別の場所に保護コンテンツを作り、それをショートコードで呼び出すという方法です。
機能の概要
以下が機能実装の概要です。
- パスワード保護コンテンツ用のカスタム投稿タイプを作る
- 1のコンテンツ全体にパスワード保護をかける(WordPress標準のパスワード保護機能を使う)
- 1のコンテンツを取得して表示させるショートコードを作り、投稿や固定ページの適所に挿入して機能させる
- 1の投稿タイプは管理者権限以外のユーザーには表示させない
- 管理者権限以外のユーザーが直接アクセスした場合にはトップページへリダイレクトさせる
- 検索の対象外にする
- アーカイブを作らないようにする
まあ要はWordPress標準のパスワード保護機能がコンテンツ全体に掛かってしまうものだから、それ自体を投稿や固定ページとは別に作ってショートコードで呼び出すというものです。
カスタム投稿タイプも、パスワード保護もWordPress標準の機能として備わっているものですから、次項の囲み型ショートコードのように長いコードを書く必要もありませんし、フォームや認証に関するセキュリティ面でも比較的安全なのではないかと思います。
1点、保護コンテンツ自体は別の場所での編集となり、保護コンテンツを含む投稿の編集画面からは直接見えないので、管理しにくい感じはしますが、管理者権限を持つユーザーにはフロントエンドのフォーム内にパスワードを表示させるなどの工夫をすることで動作確認がしやすくなると思います(この方法については本ページでは割愛していますので頑張ってカスタマイズしてください)。
パスワード保護コンテンツの動作デモ
以下実際の動作デモです。パスワードに「12345」と入力し、送信ボタンをクリックするとコンテンツが表示される仕組みです。
追加するコード
実装は以下のコードを順にfunctions.phpへ追加して行います。
パスワード保護コンテンツ用のカスタム投稿タイプを作る
まずは保護コンテンツ用の投稿タイプ(投稿や固定ページとは別のコンテンツの集まり)を作ります。
/* コンテンツ用の投稿タイプを作る */
function pwcn_create_protected_content_custom_post_type() {
register_post_type('protected_content',
array(
'labels' => array(
'name' => __('Protected Contents'),
'singular_name' => __('Protected Content')
),
'public' => true,
'exclude_from_search' => true, // 検索エンジンから除外
'has_archive' => false, // アーカイブを無効にする
'supports' => array('title', 'editor', 'author', 'thumbnail', 'revisions'),
'rewrite' => array('slug' => 'protected-content'), // スラッグを設定
'show_in_rest' => true, // ブロックエディターを有効にするために追加
)
);
}
add_action('init', 'pwcn_create_protected_content_custom_post_type');
パスワードコンテンツへの直接アクセスを禁止(リダイレクト)させる
カスタム投稿タイプの追加部分で外からは完全なURLが分からなければ見えないものの、一応直接アクセスされた時にトップページへリダイレクトさせる機能を追加します。
保護コンテンツの作成時にプレビューや表示ができるよう、管理者権限ではリダイレクトされないようにしています
/* 管理者以外は直接アクセスさせない(トップページへリダイレクト) */
function pwcn_redirect_protected_content() {
if (is_singular('protected_content') && !current_user_can('administrator')) {
wp_redirect(home_url()); // ホームページにリダイレクト
exit;
}
}
add_action('template_redirect', 'pwcn_redirect_protected_content');
フィードから除外
register_posttype()では、feedへの出力の制御ができず、RSSリーダーなどで表示した際に保護コンテンツが含まれてしまうので、以下のコードを使って除外します。
/* feedから除外 */
function pwcn_exclude_protected_content_from_feed($query) {
if ($query->is_feed() && $query->is_main_query()) {
// 除外したいカスタム投稿タイプのスラッグを指定
$post_types = $query->get('post_type');
// $post_typesが配列でない場合は配列に変換
if (!is_array($post_types)) {
$post_types = array($post_types);
}
$query->set('post_type', array_diff($post_types, array('protected_content')));
}
}
add_action('pre_get_posts', 'pwcn_exclude_protected_content_from_feed');
パスワード保護コンテンツを挿入するショートコードを作る
/* ショートコードで投稿内へ表示(パスワード保護はWordPress標準機能を利用) */
function pwcn_display_protected_content($atts) {
$atts = shortcode_atts(array(
'id' => '', // 投稿IDを指定するための属性
), $atts);
// 投稿IDが指定されていない場合はエラーメッセージを返す
if (empty($atts['id'])) {
return '<p>表示するコンテンツのIDを指定してください。</p>';
}
// パスワード保護コンテンツを取得
$query = new WP_Query(array(
'post_type' => 'protected_content',
'p' => $atts['id'], // IDで指定された投稿を取得
));
// パスワード保護コンテンツが見つからない場合はエラーメッセージを返す
if (!$query->have_posts()) {
return '<p>該当するコンテンツが見つかりません。</p>';
}
// パスワード保護コンテンツの本文を表示
ob_start();
while ($query->have_posts()) {
$query->the_post();
// パスワードが必要な場合の処理
if (post_password_required()) {
return get_the_password_form();
}
// コンテンツを表示
echo '<div>' . apply_filters('the_content', get_the_content()) . '</div>';
}
wp_reset_postdata();
return ob_get_clean();
}
add_shortcode('protected_content_display', 'pwcn_display_protected_content');
追加するコードは以上です。案外少ないコードで実装できます。
入力フォームの文字列の変更、スタイルを変更しやすくする
WordPress標準のパスワード入力フォームはメッセージがちょっと素っ気ないのと、CSSクラスが最小限になっていてスタイルの変更がしにくい部分があるので、以下のコードを使ってフォームをちょっと改造します。
function pwcn_customize_password_form() {
global $post;
$label = 'pwbox-'.( empty( $post->ID ) ? rand() : $post->ID );
$message = __( '続きを見るにはパスワードを入力してください' );
$label_text = __( 'パスワード:','' );
$submit_text = __( '送信','' );
$class_prefix = 'pwcn-password-form';
$output = '';
$output = '<div class="'.$class_prefix.'-wrap">';
$output .= '<form action="' . esc_url( site_url( 'wp-login.php?action=postpass', 'login_post' ) ) . '" method="post" class="'.$class_prefix.'-forms">';
$output .= '<p class="'.$class_prefix.'-message">';
$output .= $message;
$output .= '</p>';
$output .= '<div class="'.$class_prefix.'-form">';
$output .= '<label for="' . $label . '" class="'.$class_prefix.'-label">';
$output .= $label_text;
$output .= '</label>';
$output .= '<input name="post_password" id="' . $label . '" type="password" size="20" maxlength="20" class="'.$class_prefix.'-input-field" />';
$output .= '<input type="submit" name="Submit" value="' . esc_attr( $submit_text ) . '" class="'.$class_prefix.'-submit-btn" />';
$output .= '</div>';
$output .= '</form>';
$output .= '</div>';
return $output;
}
add_filter( 'the_password_form', 'pwcn_customize_password_form' );
こうしておけば文字列の変更は自由にできるし、ある程度の場所にCSSクラスが当たるのでスタイルのカスタマイズがしやすくなります。
パスワード保護コンテンツの作り方
保護コンテンツを作成する
コード追加後に管理画面をリロードすると、メインメニューに「Protected Contents」というメニューが追加されます。
これが後にパスワードで制御するコンテンツになります。
通常の投稿のようにパスワードで保護するコンテンツを作ます。
右側のパネルを開き、「Protected Contents」タブを開き、下図のように「下書き」をクリック後表示される別窓の一番下欄でパスワードを設定します(「パスワード保護」にチェックを入れ、任意のパスワードをセットします)。

コンテンツを公開します。
公開後、「Protected Contents」の一覧からクイック編集を開き、「パスワード」欄でパスワードを指定したり、変更したりすることも可能です
これで準備は完了です。
パスワード付きコンテンツを呼び出す
以下のショートコードをパスワード付きコンテンツを挿入した場所へ追加します。
[protected_content_display id=""]
IDパラメーターの部分は「Protected Contents」の一覧からタイトルなどをマウスオーバーした時画面下部に表示されるURLの「id=〇〇」の部分の数字を指定します。
もしも管理画面上でIDを表示させたいという方は以下を参考にしてみてください。
さらに工夫するなら、IDの列の代わりにコピーできるようにショートコードそのものを表示させるのも手だと思います(今回の主旨から外れるので作り方は割愛します)。
これでテストを行ってみて、ショートコードを挿入した場所が以下のようになっていれば実装完了です。

当初は次項のショートコードで実装しようと右往左往していましたが、案外簡単に実装できちゃったという印象でした(笑)。
パスワード保護コンテンツの動作について
パスワード保護の動作についてはWordPress公式の機能を利用していますので、正確なところは「投稿をパスワードで保護する」を参照することをおすすめしますが、一応このような動作をするようです。
- パスワードの長さは20文字までを指定できます
- 同じパスワードのコンテンツは再度パスワード入力しなくても閲覧できるようですが、翻訳してみても内容が不明瞭で、複数の投稿にまたがる場合などには違った動きをするかも知れません(よくテストすることをおすすめします)
- カスタムフィールドを使ったデータはパスワード保護とは関係なく表示されるようです
なお、「投稿をパスワードで保護する」にも書かれている通り、この動作はフィルターを使ってある程度カスタマイズできるようになっているようです。
2.囲み型ショートコードで作る方法
保護するコンテンツをショートコードで囲む方法です。
1の方法とは違って別の場所にパスワード保護コンテンツを作るのではなく、投稿編集画面内で保護コンテンツを直接見て編集できるのがメリットかと思います。
以下を有効化しているテーマのfunctions.phpへ追加して試してみてください(コードの詳細は割愛しますのでご自身で調べてください)。
function pwcn_password_protected_box($atts, $content = null) {
$atts = shortcode_atts(array(
'password' => '',
'cookie' => 'false', // デフォルトはクッキー無効
'expire' => '3600', // デフォルトの有効期限は1時間(3600秒)
), $atts);
// エラーメッセージの初期化
$error_message = '';
$is_authenticated = false;
// クッキーが有効な場合の処理
if ($atts['cookie'] === 'true' && isset($_COOKIE['protected_content_authenticated']) && $_COOKIE['protected_content_authenticated'] === 'true') {
$is_authenticated = true; // クッキーが存在する場合、認証済み
}
// POSTリクエストがあった場合
if (isset($_POST['password_input'])) {
// Nonceの検証
if (!isset($_POST['_wpnonce']) || !wp_verify_nonce($_POST['_wpnonce'], 'protected_content_nonce')) {
$error_message = '<p style="color: red;">無効なリクエストです。</p>';
} else {
// 入力をサニタイズ
$input_password = sanitize_text_field($_POST['password_input']);
if ($input_password === $atts['password']) {
// 正しいパスワードが入力された場合、クッキーを設定
if ($atts['cookie'] === 'true') {
setcookie('protected_content_authenticated', 'true', time() + intval($atts['expire']), '/'); // 有効期限を設定
}
$is_authenticated = true; // 認証済み
} else {
// パスワードが間違っている場合のエラーメッセージ
$error_message = '<p style="color: red;">パスワードが違います。</p>';
}
}
}
// 認証済みの場合、コンテンツを表示
if ($is_authenticated) {
return '<div class="protected-box">' . do_shortcode($content) . '</div>';
}
// フォームを表示
$form = '<form method="post" class="password-form">';
$form .= '<label for="password_input">パスワードを入力してください:</label>';
$form .= '<input type="password" name="password_input" required>';
$form .= wp_nonce_field('protected_content_nonce', '_wpnonce', true, false); // Nonceフィールドを追加
$form .= '<button type="submit">送信</button>';
$form .= '</form>';
return '<div class="protected-box">' . $error_message . $form . '</div>';
}
add_shortcode('pwcn_protected_content', 'pwcn_password_protected_box');
[pwcn_protected_content password="パスワード" cookie="true" expire="7200"]
ここに表示させたいブロックを追加
[/pwcn_protected_content]
コメントを残す