読者です 読者をやめる 読者になる 読者になる

プログラマでありたい

おっさんになっても、プログラマでありつづけたい

Apacheの基本認証をDBを使って行うmod_auth_mysql

 手軽にApacheで認証を行ないたくて、mod_auth系のモジュールを探ってみました。パスワードファイルではなくてDBを使って認証できないかと思って見ていると、主要DBに対しては一通り揃っていました。その中でmysqlに対応しているのが、mod_auth_mysql。使い方は割と簡単で、CONFIGUREを読めば大体理解できます。

CentOSだと、次のコマンドで一発で追加できます。

yum install mod_auth_mysql

また、以下のファイルが追加されているはずです。
/etc/httpd/conf.d/auth_mysql.conf


 ファイル中には色々な設定例が載っていますが、基本的な部分をピックアップすると次のようになります。認証に使うデータベース名やDBに対するユーザ名、パスワード。そして認証に使うデータを格納したテーブル、カラムを指定します。またパスワードの暗号化方式を決めます。

LoadModule mysql_auth_module modules/mod_auth_mysql.so

<Directory /var/www/html/auth_zone>
    AuthName "MySQL authenticated zone"
    AuthType Basic

    AuthMYSQLEnable on
    AuthMySQLUser user_name
    AuthMySQLPassword user_password
    AuthMySQLDB database_name
    AuthMySQLUserTable users
    AuthMySQLNameField login_name
    AuthMySQLPasswordField crypted_password
    AuthMySQLPwEncryption sha1
    require valid-user
</Directory>

 パスワードの暗号化方式の部分以外はあまりハマる要素はないのですが、MySQLのログを見ながら確認するとスムーズにいくと思います。mysqlのクエリログを出す場合は、my.cnfの[mysqld]の部分にlogの一文を追加して再起動すれば/var/lib/mysql/mysqld.logにクエリ等のログが出るようになります。(/var/lib/mysqlは、mysqlのインストール場所)
 例えば、上記の設定でWebから認証しようとしたら下記のようなログが出ます。

SELECT crypted_password, length(crypted_password) FROM users WHERE login_name='hoge'


 また基本的な設定の他に、様々なオプション設定が出来ます。例えば、特定のカラムに対する条件を追加することも可能です。
AuthMySQLUserCondition = "status = 'active'"

SELECT crypted_password, length(crypted_password) FROM users WHERE login='hoge' AND status = 'active'

 応用でテーブルを結合することも可能で、別テーブルのカラムも認証項目とすることも可能です。
AuthMySQLUserTable "users, user_status"
AuthMySQLUserCondition "users.user_name = user_status.user_name and user_status.status = 'active'"

SELECT crypted_password, length(crypted_password) FROM users, user_status WHERE login='hoge' AND users.user_name = user_status.user_name and user_status.status = 'active'

 またアクセス元の情報を、認証条件に追加することも可能です。例えばIPアドレスで絞る場合は、次のようになります。
AuthMySQLUserCondition "ip_address = '%a'"
 ちなみに公式ページの例は、一部間違っているか古くてAuthMySQLUserConditionの例が、次のようになっています。設定名の後のイコールは不要なので注意してください。
AuthMySQLUserCondition = "ip_address = '%a'"


 さらにさらにsaltフィールドとかも使えます。ただし、暗号化方式がcryptかaesの場合のみのようです。saltとはなんぞやと言いますと、元パスワードに付加的な情報を追加して暗号化することにより、より元のパスワードを推測しづらくする方法です。


 このように色々とこなれていて、かつ枯れているので安心して使えます。アプリケーションによる認証をかまさずに簡単に認証したい場合は検討しても良いのではないでしょうか?WebDavと組み合わせるとか、良いアイデアなんじゃないかと思います。