baserCMS フロント認証機能を使ったメンバー専用ページ作成時のケーススタディ

- 2021/12/12 追記
「baserCMS 当たり前にやっておきたいセキュリティー対策の基本」でも触れましたが、以下の設定で、管理画面およびフロント認証のセッションキーを共有した場合、フロント認証画面からも管理システムの「admin」権限のログインが可能になることから、相応のセキュリティ上の配慮が必要になると思います。

話を進める前に、少しだけ寄り道。 そもそも、baserCMSの「フロント認証」と「マイページ認証」は、何がどう違うのか、どの様な使い分けなのか。baserCMS初心者には、当初なかなか理解できなかったので少し触れておきます。 本来、ネーミングの通り「フロント認証」は、フロント側の画面(つまり一般ユーザーが閲覧するページ)に認証をかけて、閲覧者を制限することができる機能です。つまり、メンバー限定とか会員限定用のサイトを作成したい場合、あるいは、サイト内の特定のページをアクセス権限をもった特定のメンバーとか会員にのみ閲覧を許可させたい場合などに利用します。 次に「マイページ認証」とは、既にデザインされているフロント側の画面に縛られず、マイページ認証による閲覧を許可されたメンバーとか会員にのみ別のレイアウトファイルなどを適用した別のデザインのページを作成、閲覧させることができます。マイページログイン画面も独自にデザインすることができます。 (いやいや、そういうことじゃないよ、というお叱りがあれば是非教えてください。)

というわけで、今回は、baserCMSの「フロント認証」機能を利用して現状のサイト内に「メンバーのみアクセス可能なページを作成したい」というようなケースに絞って話を進めたいと思います。

さて、本トピックのタイトルに沿ってメンバー専用ページの作成を考える場合、そのサイト利用者は、管理・運用する主な権限者、メンバー専用ページを閲覧できるメンバー(baserCMSでいうところのユーザーグループ、細かくはユーザー)および一般のサイトの閲覧者に分けられ、その詳細は、概ね以下のようになるのではないでしょうか。

A. サイト管理者(管理システムに「admin」権限でアクセスし、サイト全体の管理を行う管理者)
B. サイト運用者(管理システムに「operator」権限でアクセスし、ブログなどの記事を作成したり、編集するコンテンツ運用者)
C. メンバー(管理ページにアクセスする権限はなく、フロントサイドのユーザーログイン画面から認証し、メンバー専用ページを閲覧できる限られたメンバー)
D. メンバー以外の一般のサイト閲覧者

ここで、上記AからCの利用者が、管理・運用上利用するであろう各ログイン画面を例にスタディしたいと思います。 ちなみに③は、今回のテーマには直接関係しませんが、マイページ認証を利用した場合のデフォルトのマイページログイン画面です。参考までに。 画像の説明

A、Bの利用者は、サイト管理者およびサイト運用者なので、通常は①管理システムログイン画面から管理システムにログインし、必要な作業を行います。

次に、AからCの利用者について、メンバー専用ページに対する閲覧権限の有無の観点で考えた場合、おそらくA、B(Cは当然)の利用者も、相当なケースでメンバー専用ページ閲覧権限も同時に与えられると思われます。

とすると、A、Bの利用者は、それぞれの権限で管理システムにログインしている状態の時に、あらためて②ユーザーログイン画面から別途ログイン行為をしないとメンバー専用ページを閲覧できないというのは、ちょっと面倒だし、なにやら不合理な感じすらします。 つまり、A、Bの利用者は、①は当然ながら、②のログイン画面からでも、自身のアカウント名、パスワードで区別なく、ログインが可能でありたいはず。

そこで、baserCMS備え付け?のデフォルト設定や用意されたサンプルを使って、そのような運用に素直になるのか?と言えば、然に非ずというのが、このケーススタディのトピックを上げる動機になっています。

とは言え、そもそも、①、②、③は、本来、A、BおよびCの利用者に対して個別にアサインされている権限を行使する目的で、個別に用意されているログイン画面なので、本来は独立して扱えるべきものというのが現在のbaserCMSの設計思想なのだとおもいます。そういう要件だって、もちろんあるわけだし。つまりは、いずれのケースでもうまい運用ができる、運用の仕方や要点が理解できれば良いわけです。(この辺りのことは、既に3系から機能としては実装されているので、自分で書いていて事情の説明がややこしいw)

画像の説明 上図は、フロント認証やマイページ認証をsetting.phpで適用させた場合、ユーザーグループの編集画面上に表示される「認証プレフィックス設定」のチェックボックスです。

このUIを見れば、上述のようにAの利用者に「フロント」(メンバーサイト閲覧の権限)を適用したくなりますよね? で、「管理システム」(この場合、adminsなので有無を言わさずチェックされています)と「フロント」にチェックを入れて保存すると、ちょっと困ったことになります。

事情を説明する上で前後しましたが、フロント認証を適用させる場合、本来は、以下のsetting.phpの作業が手順としては先に行われています。 baserCMS4系のBaser/Config/setting.phpに記載されている「認証プレフィックス設定」の関する記述部分(520行目辺りから578行目辺り)を/app/Config/setting.phpにコピーして、'front'の認証プレフィックス設定のコメントアウトを外すという作業です。 ざっくり以下の様になります。

$prefixes = Configure::read('Routing.prefixes');
$adminPrefix = $prefixes[0];
$config['BcAuthPrefix'] = [
    'admin' => [
    // 省略
    'sessionKey' => 'Admin',
    // 省略
    ],
    'front' => array(
    // 省略
        'logoutAction'=> '/users/logout',
    // 省略
    'sessionKey' => 'User',
    // 省略
    )
];

この'sessionKey'が個別に設定されているため、管理画面およびフロント認証(場合によってはマイページ認証)それぞれにログイン、ログオフの操作を独立して行うことができるようになります。 言い方を変えると個別にログイン、ログオフの操作を行う必要がでてきます。 で、実際に個別にログインしたのち、ログオフをしようとすると、管理画面からのログオフはこれまで通り管理ツールバーから行うことができますが、フロント認証のログオフができないという事態に見舞われます。 つまり、'logoutAction'=> '/users/logout'のUIがなく、というか管理ツールバーは表示されるもののあくまで管理画面用として表示され続けるため、直接、/users/logoutのURLをたたくしかフロント認証からログオフする方法がありません。

私事ながらbaserCMSの運用歴は2系からなのですが、フロント認証を利用し始めたbaserCMS3系(3系初期はまた事情が多少違う様ですが)では、'admin' => []'sessionKey''sessionKey' => 'User'となっていて、事実上'front' => []'mypage' => []'sessionKey'と同じだったので、上述の管理画面およびフロント認証のセッションキーの共有は、自然に意図せず実現していました。 それが、baserCMS4系にメジャーバージョンアップしたタイミングで、'admin' => []'sessionKey''sessionKey' => 'Admin'と変更され、事実上'front' => []'mypage' => []'sessionKey' => 'User'と区別される格好になったため、あれ?なにやらチグハグな運用になってるなぁ、というのが現状です。

実際の運用手順

長々と事情を話した挙句、結論はとても唐突なのですが、Aの利用者にメンバー専用ページへのアクセス権を許可する場合、私は、以下の様に/app/Config/setting.phpを記述して、'admin' => []'front' => []'sessionKey'を共有させて運用しています。

対象ファイル:/app/Config/setting.php

<?php
/**
 * baserCMS :  Based Website Development Project <http://basercms.net>
 * Copyright (c) baserCMS Users Community <http://basercms.net/community/>
 *
 * @copyright       Copyright (c) baserCMS Users Community
 * @link            http://basercms.net baserCMS Project
 * @package         Blog.Config
 * @since           baserCMS v 0.1.0
 * @license         http://basercms.net/license/index.html
 */

/**
 * baserCMS アプリケーション設定
 *
 * `/lib/Baser/Config/setting.php` に全ての設定が記述されています。
 * 必要な設定をこのファイルに記述するとこちらが優先されます。
 *
 * (例)
 * $config['BcApp'] = [
 *  'title' => __d('baser', 'Custom baserCMS')
 * ];
 */

 /**
 * 認証プレフィックス設定
 * ※ CSVは非対応
 */
$prefixes = Configure::read('Routing.prefixes');
$adminPrefix = $prefixes[0];
$config['BcAuthPrefix'] = [
    // 管理画面
    'admin' => [
        // 認証タイプ
        'type' => 'Form',
        // 認証設定名
        'name' => __d('baser', '管理システム'),
        // URLにおけるエイリアス
        'alias' => $adminPrefix,
        // 認証後リダイレクト先
        'loginRedirect' => '/' . $adminPrefix,
        // ログイン画面タイトル
        'loginTitle' => __d('baser', '管理システムログイン'),
        // ログインページURL
        'loginAction' => '/' . $adminPrefix . '/users/login',
        // ログアウトページURL
        'logoutAction' => '/' . $adminPrefix . '/users/logout',
        // ツールバー利用
        'toolbar' => true,
        // モデル
        'userModel' => 'User',
        // セッションキー
        'sessionKey' => 'Admin',
        // preview及びforce指定時に管理画面へログインしていない状況下での挙動判別
        // true:ログイン画面へリダイレクト
        // false:ログイン画面へリダイレクトしない
        // @see /lib/Baser/Routing/Route/BcContentsRoute.php
        'previewRedirect' => true
    ],
    // フロント(例)
     'front' => [
          'name'            => __d('baser', 'フロント'),
          // メンバー専用サイトのトップ画面のURL
          'loginRedirect'   => '/members_top',
          // ログイン画面タイトル
          'loginTitle' => __d('baser', '会員ページログイン'),
          'userModel'       => 'User',
          'loginAction' => '/users/login',
          'logoutAction'=> '/users/logout',
          'toolbar'     => true,
          // コピー元は 'User' ですが、'Admin' に変更
          'sessionKey'  => 'Admin'
    ]
    // マイページ(例)
    /* 'mypage' => [
          'name'            => __d('baser', 'マイページ'),
          'alias'           => 'mypage',
          'loginRedirect'   => '/mypage/members/index',
          'loginTitle'  => __d('baser', 'マイページログイン'),
          'userModel'       => 'Member',
          'loginAction' => '/mypage/members/login',
          'logoutAction'=> '/mypage/members/logout',
          'toolbar'     => false,
          // コピー元は 'User' ですが、'Admin' に変更
          'sessionKey'  => 'Admin'
    ] */
];

認証をかけたいメンバー専用ページのURLが/members_top/members_blogという想定で、 その他の手順に関しては、以下の@beychanさんの記事を参考にさせていただいています。
[baserCMS] フロント認証

対象ファイル:/app/Controller/AppController.php

<?php
App::uses('BcAppController', 'Controller');
class AppController extends BcAppController {
    public function beforeFilter() {
        parent::beforeFilter();
        if(BcUtil::isAdminSystem()) {
            return;
        }
        // フィードの場合はスルー(管理画面のダッシュボードで読み込まれているため)
        if(preg_match('/^feed\//', $this->request->url)) {
            return;
        }
        // 認証クラスがない場合はスルー
        if(!isset($this->BcAuth)) {
            return;
        }
        // ログイン画面の場合はスルー
        if(('/' . $this->request->url) == $this->BcAuth->loginAction) {
            return;
        }
        // パスワードリセット画面の場合はスルー
        if(($this->request->url) == 'users/reset_password') {
            return;
        }
        // リクエストアクションの場合はスルー
        if($this->request->is('requested')) {
            return;
        }
        // 認証をかけたいメンバー専用ページのURLをpreg_match関数で抽出、かつ認証されていない場合はログイン画面にリダイレクト
        if(preg_match('/members_top|members_blog/', $this->request->url) && !$this->BcAuth->user()) {
            $this->redirect($this->BcAuth->loginAction);
        }
    }
}

最後にbaserCMSは、ページビューキャッシュを利用する為、キャッシュのチェックをオフにしないと、認証がかかっていてもキャッシュされたページが表示されてしまいます。そのため、以下の設定を確認し、('Cache.check', true); なら false に変更。無ければ、加えてキャッシュをオフに設定します。

対象ファイル:/app/Config/install.php

Configure::write('Cache.check', false);

コメント


コメントする


Wp86hp