- 追加された行はこの色です。
- 削除された行はこの色です。
[[../]]
*任意のページごとの閲覧・編集制限 -- [[Ynak]] [#b0e3a2f6]
※旧「BASIC認証で任意のページごとに閲覧制限や編集制限をかける方法」。名前が長すぎなので修正しました。
#contents
**やりたいこと [#f26d6529]
任意のページごとに閲覧制限や編集制限をかけたい。((Wikiの思想に逆行するのは重々承知の上です。))
具体的には
+××ページは全員が閲覧できるが、内容を編集できるのは○○だけ。
+△△ページは□□だけが閲覧・編集できる。
+○△ページは□□だけが閲覧できるが、編集は○○だけ。
というようなことをやりたい。
**現状 [#n98e6dfb]
-他のWikiEnginesでは、実装されているものもある。
-PukiWiki1.3.xでは、実装されていない。
-かろうじて使用できるのがページ内容の凍結であるが、PukiWiki全体で1つのパスワード設定しかできないので、運用面で困る。
**方針 [#tb83a099]
[[PukiWiki/1.4/BasicAuth]]で紹介されている方法をそのまま使えば、全ページに対する編集権限を設定できる。
更に、コメント部で紹介された方法((多少修正が必要であるが。))を使用すれば、正規表現で定義されたページ名に対する編集権限を1セット設定できる。
しかし、最終目標には少々足りていないので、更なる改造が必要。
**仕様 [#s05d1c04]
pukiwiki.ini.phpで
|ユーザID|パスワード|
|正規表現によるページ名のパターン|閲覧できるユーザID(カンマ区切り)|
|正規表現によるページ名のパターン|編集できるユーザID(カンマ区切り)|
を定義することで、ちょっとUNIXライクな読み書き((関係ないけど、送りがなを詰めると''読書''になるって知ってた?))権限の設定ができる。
**改造方法((diff形式じゃなくてすみません。)) [#rb4e61a7]
PukiWiki1.3.4をベースに改造する方法は以下の通り。
***ja.lng [#sc6cff98]
以下を追加する。
$_msg_auth = 'PukiWikiAuth';
$_title_cannotread = '$1 は閲覧できません';
***en.lng [#v8077a9e]
以下を追加する。
$_msg_auth = 'PukiWikiAuth';
$_title_cannotread = '$1 is not readable';
***func.php [#ja82bba5]
以下を追加する。
/////////////////////////////////////////////////////////////////
// Basic認証による権限チェック
function edit_auth() {
global $get, $_title_cannotedit;
global $edit_auth, $auth_users, $_msg_auth;
global $vars, $edit_auth_pages;
// 編集認証フラグをチェック (システム全体として編集認証するかどうか)
if (!$edit_auth) {
return;
}
// 認証が必要なページかどうかをチェック
$edit_auth_users = "";
while (list($key, $val) = each($edit_auth_pages)) {
if (preg_match($key, $vars['page'])) {
$edit_auth_users = $val;
break;
}
}
if ($edit_auth_users == "") {
return;
}
// 認証を行う
if ((!isset($_SERVER['PHP_AUTH_USER']) or
!preg_match("/".$_SERVER['PHP_AUTH_USER']."/", $edit_auth_users) or
!array_key_exists($_SERVER['PHP_AUTH_USER'], $auth_users) or
$auth_users[$_SERVER['PHP_AUTH_USER']] != $_SERVER['PHP_AUTH_PW']))
{
header('WWW-Authenticate: Basic realm="'.$_msg_auth.'"');
header('HTTP/1.0 401 Unauthorized');
// press cancel.
$body = $title = str_replace('$1', htmlspecialchars(strip_bracket($get['page'])), $_title_cannotedit);
$page = str_replace('$1',make_search($get['page']),$_title_cannotedit);
catbody($title, $page, $body);
exit;
}
}
function read_auth() {
global $get, $_title_cannotread;
global $read_auth, $auth_users, $_msg_auth;
global $vars, $read_auth_pages;
// 閲覧認証フラグをチェック (システム全体として編集認証するかどうか)
if (!$read_auth) {
return;
}
// 認証が必要なページかどうかをチェック
$read_auth_users = "";
while (list($key, $val) = each($read_auth_pages)) {
if (preg_match($key, $vars['page'])) {
$read_auth_users = $val;
break;
}
}
if ($read_auth_users == "") {
return;
}
// 認証を行う
if ((!isset($_SERVER['PHP_AUTH_USER']) or
!preg_match("/".$_SERVER['PHP_AUTH_USER']."/", $read_auth_users) or
!array_key_exists($_SERVER['PHP_AUTH_USER'], $auth_users) or
$auth_users[$_SERVER['PHP_AUTH_USER']] != $_SERVER['PHP_AUTH_PW']))
{
header('WWW-Authenticate: Basic realm="'.$_msg_auth.'"');
header('HTTP/1.0 401 Unauthorized');
// press cancel.
$body = $title = str_replace('$1', htmlspecialchars(strip_bracket($get['page'])), $_title_cannotread);
$page = str_replace('$1',make_search($get['page']),$_title_cannotread);
catbody($title, $page, $body);
exit;
}
}
***pukiwiki.php [#mfc298c7]
編集制限が必要な追加・編集・プレビュー等の箇所に
edit_auth();
を、閲覧制限が必要な表示関係の箇所に
read_auth();
を挿入する。
-103行付近
// 追加
else if(arg_check("add"))
{
edit_auth(); // ★これを挿入!
-113行付近
// 編集
else if(arg_check("edit"))
{
edit_auth(); // ★これを挿入!
-124行付近
// プレビュー
else if(arg_check("preview") || $post["preview"] || $post["template"])
{
edit_auth(); // ★これを挿入!
-195行付近
// 書き込みもしくは追加もしくはコメントの挿入
else if($post["write"])
{
edit_auth(); // ★これを挿入!
-384行付近
// 差分の表示
else if(arg_check("diff"))
{
read_auth(); // ★これを挿入!
-462行付近
// バックアップ
else if($do_backup && arg_check("backup"))
{
read_auth(); // ★これを挿入!
-629行付近
// WikiName、BracketNameが示すページを表示
if(is_page($get["page"]))
{
read_auth(); // ★これを挿入!
-641行付近
else if(preg_match("/($InterWikiName)/",$get["page"],$match))
{
read_auth(); // ★これを挿入!
-722行付近
if(preg_match("/^(($BracketName)|($WikiName))$/",$get["page"])) {
edit_auth(); // ★これを挿入!
-736行付近
// 何も指定されない場合、トップページを表示
else
{
read_auth(); // ★これを挿入!
***pukiwiki.ini.php [#hd8d4502]
以下のように設定を追加する。
下記は設定例のため、設定内容は適切に変更すること。
//////////////////////////////////////////////////
// 閲覧・編集制限の設定
// 認証のアカウント
// ユーザ名とパスワードを記入。
$auth_users = array(
'foo' => 'foo_passwd',
'bar' => 'bar_passwd',
'hoge' => 'hoge_passwd',
);
// 編集時に認証が必要か
$edit_auth = 1;
// 編集認証をかけるページ名のパターンを正規表現で設定する。
// マッチしたページに編集認証をかける。
// カンマ区切りで複数ユーザを書いても良い。
$edit_auth_pages = array(
'/Barの公開日記/' => 'bar',
'/ひきこもるほげ/' => 'hoge',
'/(ネタバレ|ねたばれ)/' => 'foo',
);
// 閲覧時に認証が必要か
$read_auth = 1;
// 閲覧認証をかけるページ名のパターンを正規表現で設定する。
// マッチしたページに編集認証をかける。
// カンマ区切りで複数ユーザを書いても良い。
$read_auth_pages = array(
'/ひきこもるほげ/' => 'hoge',
'/(ネタバレ|ねたばれ)/' => 'foo,bar,hoge',
);
上の例では
-「Barの公開日記」は、誰でも閲覧できて、barだけが編集できる。
-「ひきこもるほげ」ページは、hogeだけが閲覧・編集できる。
-「映画紹介~ネタバレ注意」ページは、foo, bar, hogeの三人だけが閲覧できて、かつ、編集はfooだけが可能。
のような設定となる。
かなり強引にUNIXっぽく表現すると、こうなる。
アクセス権 ユーザID グループ ページ名
-rw----r-- bar なし Barの公開日記
-rw------- hoge なし HogeOnly
-rw-r----- foo hoges 映画紹介~ネタバレ注意
※グループhogesには、barとhogeが所属するとする。
**注意点 [#ae8cccdb]
-初めてPHPをさわった人間が改造しているので、実装的に問題があるかも。
--添削希望。
-閲覧認証をかけたページは、編集認証も必須。
--でないと、「編集」リンクから内容が読めてしまったり、挙動が怪しくなったりする。((UNIXでも、rw-(閲覧認証&編集認証の同時設定)はOKだけど、 -w-(編集認証のみ)はいろいろと問題が発生するのと似てる。))
--編集可能ユーザは、閲覧可能ユーザのサブセットとなるように設定すること。
-edit_auth_pagesなどのvalue部分と、BASIC認証のユーザ名の比較をpreg_matchで行っているので、あるユーザIDのサブセットとなるようなユーザIDがあるとややこしくなる。
--例えば、'hogefoobar'というユーザIDがあって、このユーザだけが編集できるようなページを以下のように設定する状況を考える。
$edit_auth_pages = array(
'/Secret/' => 'hogefoobar',
);
--ここでもし、'hoge'、'foo'、'bar'というユーザIDが存在していれば、そのいずれかのユーザIDでBASIC認証を突破すれば、このSecretページにアクセスできてしまう。
--とりあえず、pukiwiki.ini.phpにユーザID設定をする人が気を付ければ良いので、気にしていませんが、良い回避法があれば修正してください。
*コメント [#fa4b735d]
-うおお、 おみごと。ページ単位の認証ってニーズ高いですもんね。 -- [[yateeight]] &new{2003-05-17 (土) 17:10:37};
-実は、オートリンクとNoBracketNameが素敵なので1.4に乗り換えようとしてます。で、1.4も同じように改造しようとしてますが、1.3.4とだいぶ作りが違うので難儀してるところです。 -- [[Ynak]] &new{2003-05-17 (土) 20:30:32};
-おっと、includeプラグインで無権限者による閲覧ができる穴発見。 -- [[Ynak]] &new{2003-05-17 (土) 21:10:03};
-他にもcalendar_viewerとかその手のプラグインで続々抜け穴を発見。プラグインを無効にするか、プラグインの頭のところでread_auth()を呼ぶようにしないとだめっぽいです。 -- [[Ynak]] &new{2003-05-17 (土) 21:23:11};
-編集系プラグインはあまりないですが、閲覧系プラグインは結構あるので対処も大変ですね・・・。 -- [[Ynak]] &new{2003-05-17 (土) 21:24:26};
-暫定対処として、include,calendar_read,calendar_editは使わないのではずして、calendar_viewerは改造して第1引数を無効にしてみました。 -- [[Ynak]] &new{2003-05-17 (土) 23:15:53};
-ページ単位じゃなくって、全体(どのページも)に認証かけるのはどうすればよろしいのでしょうか?「新規」も制限かけたいのですが。 -- [[Naox]] &new{2003-05-18 (日) 09:12:37};
-Wikino -- [[Naox]] &new{2003-05-18 (日) 09:13:42};
-全ページに均一に認証をかけるのであれば、ページ名を"/.*/"とかにするとか、[[PukiWiki/1.4/BasicAuth]]のそのままの方法でやるとかが良いと思います。 -- [[Ynak]] &new{2003-05-18 (日) 12:00:09};
-あと、ここの改造方法では、新規ページ作成も制限対象に含まれています。 -- [[Ynak]] &new{2003-05-18 (日) 12:02:16};
-./wiki/なディレクトリを、Webで公開しているディレクトリであれば、その文書ファイル名を直接指定したら読めませんか?ということで、そういう場合の読者の無意味さがあるので、注意書きでも追加しないとねぇ。ということが1点。ページ単位での制御を行う上で、ページを追加時に、この php に定義を追加していくことの運用の手間というところを、なんとかすると、もっとよくなると思います。の2点。で、config じゃないですけど、とあるページで制御しつつ、そのページに制限を行う。の組み合わせはどうかなぁ?と。 -- [[upk]] &new{2003-05-18 (日) 16:05:06};
#comment