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のリライトルールより上に書かないと上手く動かないようでしたが、これでようやく終了です。
