はじめに

Basic認証情報を外部から制御(認証用ファイルを操作)したくて,何かモジュールはないものか,と探してみたところ,次のモジュールが使いやすそうだったので,かじってみました.

以下,個人的にかじった範囲でアウトプット.

メソッドいくつか

new

Authen::Htpasswdオブジェクトを生成します.これを用いて,認証ファイルを操作することになります.

1
2
my $file = '.htpasswd';
my $htpasswd = Authen::Htpasswd->new( $file, { encrypt_hash => 'crypt' } );

対象のファイルをBasic認証のために使うのであれば,encrypt_hashcrypt としておくとよさげです.(まぁデフォルト値としてセットされているので,指定する必要すらなかったりしますが...)

add_user

認証の対象となるユーザ(以下,ユーザ)を追加します.

1
2
$htpasswd->add_user( 'issm', 'hogehoge' );
$htpasswd->add_user( 'issm', 'hogehoge', 'extra1', 'extra2', ... );

2行目のように,第3引数以降を指定することで,その他な情報も保存することができます.これらによって,ファイルには,次のように保存されます.

issm:YoOU2G7mJeIWs
issm:YoOU2G7mJeIWs:extra1:extra2

その他な情報は生で保存されますので,重要な情報はやめておいた方がいいですね.

なお,私の環境では,既に同じユーザ情報(ユーザ名)が存在する場合,次のようなエラーが返ってきました.

Can't call method "close" on an undefined value at /usr/local/share/perl/5.8.8/Authen/Htpasswd.pm line 301, <GEN1> line 1.

ということで,後述する lookup_userメソッド等でユーザの存在を確認した上で処理を行うべきでしょう.

lookup_user

指定したユーザが存在する場合,その情報を Authen::Htpasswd::Userオブジェクトで返します.

1
2
my $user1 = $htpasswd->lookup_user( 'issm' );
my $user2 = $htpasswd->lookup_user( 'hoge' );  # undef

update_user

ユーザ情報を更新します.ユーザが存在しない場合は追加されます.

1
2
$htpasswd->update_user( 'issm', 'fugafuga' );  # updated
$htpasswd->update_user( 'hoge', 'hogehoge' );  # added

ユーザの存在確認を行わないのであれば,追加も更新もこのメソッド 1つでできてしまいますね.

delete_user

指定したユーザを削除します.

1
2
$htpasswd->delete_user( 'issm' );
$htpasswd->delete_user( $user1 );

なお,指定ユーザの存在如何に関わらず,1が返ってくるみたいです.

all_users

全てのユーザを取得します.Authen::Htpasswd::Userオブジェクトのリストとして得られます.

1
2
3
4
my @users = $htpasswd->all_users;
for my $u ( @users ) {
  print $u->{username}, "\n";
}

check_user_password

ユーザのパスワードが正しいかどうかをチェックします.正しければ 1,そうでなければ 0が返ります.

1
my $result = $htpasswd->check_user_password( 'issm', 'hogehoge' );

なお,存在しないユーザを指定すると怒られますので,事前に存在確認が必要ですね.

その他な情報をごにょごにょ

add_userupdate_user で保存した「その他な情報」は,取得した Authen::Htpasswd::Userオブジェクトの extra_info プロパティでリストリファレンスとして参照することができます.

1
2
3
use Data::Dumper;
$htpasswd->update_user( 'issm', 'fugafuga', 'extra1', 'extra2', 'extra3' );
print Dumper $htpasswd->lookup_user( 'issm' )->{extra_info};
$VAR1 = [
          'extra1',
          'extra2',
          'extra3'
        ];

場合によっては,ハッシュ的に使えると幸せになれそうです(?).

1
2
3
4
5
6
7
8
9
10
11
my $issm;
 
$htpasswd->update_user(
  'issm', 'hogehoge',
  nickname => 'issm',
  location => 'Nagoya, Aichi, Japan',
);
$issm = $htpasswd->lookup_user( 'issm' );
print $issm, "\n";
$issm->{extra_info} = { @{$issm->{extra_info}} };
print Dumper $issm->{extra_info};
issm:xlFyHxIufYjWw:nickname:issm:location:Nagoya, Aichi, Japan
$VAR1 = {
          'location' => 'Nagoya, Aichi, Japan',
          'nickname' => 'issm'
        };

これでちょっと幸せになれました.

ただし,データの区切り文字として用いられているコロン(:) が保存するデータに含まれていると幸せになれません.

1
2
3
4
5
6
7
8
9
10
$htpasswd->update_user(
  'issm', 'hogehoge',
  nickname => 'issm',
  url      => 'http://blog.iwa-ya.net/',
);
$issm = $htpasswd->lookup_user( 'issm' );
print $issm, "\n";
print Dumper $issm->{extra_info};
$issm->{extra_info} = { @{$issm->{extra_info}} };
print Dumper $issm->{extra_info};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 
issm:sX8ge53gwxrto:nickname:issm:url:http://blog.iwa-ya.net/
$VAR1 = [
          'nickname',
          'issm',
          'url',
          'http',
          '//blog.iwa-ya.net/'
        ];
Odd number of elements in anonymous hash at ./1.pl line 67.
$VAR1 = {
          'nickname' => 'issm',
          'url' => 'http',
          '//blog.iwa-ya.net/' => undef
        };

こんなことになってしまいます.

おわりに

Authen::Htpasswdモジュールをざっとかじってみました.

このモジュールを使うことで,Basic認証の管理をブラウザとかからでも行うようなしくみができそうなことがわかりました.(実ファイルを扱うので,ユーザの規模は限りがあるでしょうが...)

おまけ

実のところ,数ヶ月くらい前にかじっていたわけですが,今までアウトプットをせずにきてしまいました.反省.

なお,かじった成果は DQWindowManager で使っていたりします.

こちらもあわせてどうぞ

コメントをどうぞ