実際にmod_mrubyの認証を使ってみる応用編その1です。
今回はRails製プロジェクトマネジメントソフトウェアであるRedmineとApacheの認証を連動させてみます。
なお、DBとしてsqlite3を使用している場合限定です。
今回の記事の内容は、これがやりたかったからmod_mrubyに認証機能を加えようと思った動機でもあります。
MySQLを使っていれば、mod_perl+Redmine.pmを使うとか、mod_auth_mysqlを使うとかの方法もあるんですけどね。
さて、Redmineのユーザ情報を使った認証をmod_mrubyで実現する方法は2つほど思いつくのですが、今回はRedmineのdbをsqlite3コマンド経由で呼び出して認証する方法を紹介します。
簡易なので、ユーザの所属プロジェクトやロールなどの属性は気にしていません。
sqlite3コマンド経由の簡易Redmine認証
準備:
- mrubyからプロセスを起動したり、ハッシュの計算をするのでiij/mruby版のmod_mrubyをApacheに組み込んでおきます。
- Basic認証をするので、Redmineの認証と連動したい<Location>または<Directory>にmod_mrubyのBasic認証定義を書いておきます。
考え方:
- sqlite3のdbにsqlite3コマンド経由でアクセスし、csv形式で情報を取得
- 取得した情報とパスワードを照合
スクリプトは以下のようになります。
# アクセスするsqlite3のdbファイルのパスを指定する DB_PATH="/path/to/db.sqlite3" def main() anp = Apache::AuthnProvider.new # ユーザ名がRedmineのレギュレーションを満たしているか、あらかじめ確認します。 # SQLを直接生成しているので、SQLインジェクション対策でもあります。 # if !~ ではなく、unnless =~ をつかっているのは、!~演算子が実装されていないからです。 unless anp.user =~ /^[a-z0-9_\-@\.]*$/ # Invalid format for redmine users return Apache::AuthnProvider::AUTH_DENIED end # userに対応するhashed_passwordとsaltを取得する hashed_password = salt = nil cmd = %Q!sqlite3 -csv "#{DB_PATH}" "select hashed_password, salt from users where login='#{anp.user}' and users.status=1;"! IO.popen(cmd) {|f| line = f.gets if line.nil? # No such user return Apache::AuthnProvider::AUTH_DENIED end hashed_password, salt = line.strip.split(",",2) } # RedmineのやりかたでパスワードをHash化して比較 if hashed_password == Digest::SHA1.hexdigest("#{salt}#{Digest::SHA1.hexdigest(anp.password)}") return Apache::AuthnProvider::AUTH_GRANTED else return Apache::AuthnProvider::AUTH_DENIED end end Apache.return(main())
これで認証が連動できます。
mrubyにSQLite3を組み込むと、もっと性能出るし書きやすくなりますが、現状ではここまで。
近いうちに、もう1つの例も書きます。