WordPressにおいて、特定の投稿・カテゴリーなどを登録ユーザーのみに閲覧させたいという要望はよくあること。
通常であれば、header.php の初めあたりで is_user_logged_in や is_singular などの条件分岐タグと auth_redirect で特定の条件の場合はログイン画面に遷移するコードを書けばOKです。
<?php // カスタム投稿タイプ member はログイン済みのユーザーのみ閲覧可能にする if ( !is_user_logged_in() && is_singular('member') ) { auth_redirect(); } ?>
ところが、そこに携帯端末(フィーチャーフォン)も対応させようとして、少しはまりました。
目次
要望
- サイト自体はWordPressで構築。PC、スマートフォン、携帯で閲覧できるように。
- カスタム投稿タイプ「member」の内容はID・パスワードを入力しないと閲覧できない(ただしタイトルはトップページ等にも表示させたい)。
- ユーザーの管理はWordPressで行う。
先に書いたコードはPC、スマートフォンでは何ら問題なく動作します。
(プラグイン「Theme My Login」を使い固定ページにログインフォームをつけたり、権限毎にログイン・アウト後の挙動を変更しています)
携帯での実装
さて携帯です。(なお、表示には「Ktai Style 」+独自テーマを使っています。)
Ktai Styleにも管理画面へのログイン機能がついているのですが、私の環境で上手く動作しなかったことと(もしかすると Theme My Login のせいかも)、閲覧の制限だけできればよいこと、そもそも携帯の機種によってはCookieに対応していないことからPHPでBasic認証を行うようにしました。
「phpでベーシック認証 – bnote」を参考に 携帯用テーマのfunctions.phpにコードを追加。
<?php /** * Basic認証をかける */ function basic_auth(){ if(!isset($_SERVER["PHP_AUTH_USER"])) { header('WWW-Authenticate: Basic realm="User Only"'); header('HTTP/1.0 401 Unauthorized'); header('Content-type: text/html; charset='.mb_internal_encoding()); die('認証に失敗しました<br><a href="'.ks_blogurl(false).'">HOME</a>'); } else { if(AuthenticateUser($_SERVER["PHP_AUTH_USER"],$_SERVER["PHP_AUTH_PW"])){ // この行で入力されたID・パスワードのチェックを行う // 認証成功後の処理 return true; } else { // 認証エラーの処理 header('WWW-Authenticate: Basic realm="User Only"'); header('HTTP/1.0 401 Unauthorized'); header('Content-type: text/html; charset='.mb_internal_encoding()); die('認証に失敗しました<br><a href="/".ks_blogurl(false).'">HOME</a>'); } } } /** * 入力された情報がWordPressの登録ユーザーかどうか判定 */ function AuthenticateUser($user,$pwd){ $flg = false; // 入力されたユーザー名(ID)からWordPressのユーザー情報を取得 $user_data = get_userdatabylogin($user); if(!$user_data){ // ユーザー情報がなかったら return $flg; } // WordPressの関数を使って入力されたパスワードとユーザー情報のパスワードをチェック if(wp_check_password($pwd,$user_data->user_pass,$user)) { //認証成功時の処理 $flg = true; } else { //認証失敗時の処理 $flg = false; } return $flg; } ?>
さらに携帯用テーマのheader.php に以下を追記。
<?php /* カスタム投稿タイプ member の時のみBasic認証 */ if ( is_singular('member') ) { basic_auth(); }
これで無事、閲覧制限をかけられました。
落とし穴:PHPがセーフモードの場合、BASIC認証できない
これでOKと思いきや、セーフモード(CGI版のPHP)ではBasic認証を行えません。
最後までこれに気づかなかったのは、テスト用と実際に運用する サーバーとでPHPの環境が違ったためです。
そこで「ヒットアーツ -日記ブログ- » CGI版PHPにおけるHTTP認証(Basic認証)」 を参考に、.htaccess に追記(WordPressのパーマリンクをカスタムにしている場合)。
# BEGIN WordPress <IfModule mod_rewrite.c> RewriteEngine On RewriteCond %{HTTP:Authorization} ^(.*) # ←追記 RewriteRule ^(.*) - [E=HTTP_AUTHORIZATION:%1] # ←追記 RewriteBase / RewriteRule ^index.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] </IfModule> # END WordPress
WordPressのリライトルールより上に書かないと上手く動かないようでしたが、これでようやく終了です。