実際にmod_mrubyの認証を使ってみる応用編その2です。
今回もRedmineを題材に認証を連動させてみます。
Redmineのユーザ情報を使って認証する方法その2として、RedmineのRESTインタフェースをHTTP経由で呼び出して認証する方法を紹介します。
HTTP経由呼び出しなので、Redmine以外でも簡単に応用がききます。
HTTPで認証を他システムへ委譲
準備:
- Socketを使うので、iij/mruby版のmod_mrubyをApacheに組み込んでおきます。
- Basic認証をするので、Redmineの認証と連動したい<Location>または<Directory>にmod_mrubyのBasic認証定義を書いておきます。
- Redmineの設定「RESTによるWebサービスを有効にする」をチェックして使用可能にしておきます。
考え方:
- RedmineのRESTインタフェースをHTTP経由でアクセスし、ステータスコードを取得
- 取得したステータスコードが200(OK)なら認証成功。それ以外は失敗。
スクリプトは以下のようになります。全文はgistにあげました。
HOST="127.0.0.1" PORT=80 PATH="/redmine/users/current.xml" def main anp = Apache::AuthnProvider.new credentials = [[anp.user, anp.password].join(":")].pack("m").gsub("\n", "") request = {} request['User-Agent'] = "mruby_authn_http/0.1" request['Authorization'] = "Basic #{credentials}" http = SimpleHttp.new(HOST, PORT) ret = http.request("HEAD", PATH, request) if ret.code == 200 return(Apache::AuthnProvider::AUTH_GRANTED) else return(Apache::AuthnProvider::AUTH_DENIED) end rescue => e Apache.errlogger(3, "mruby_authn_http An exception occured : #{e.inspect}") return Apache::AuthnProvider::AUTH_DENIED end ## # Simple Http # from https://gist.github.com/3765572 *SNIP* Apache.return(main())
この実装は本当に単純で、Basic認証付きでRedmineのRESTインタフェースを呼び出しているだけです。
Basic認証は、Authorizationヘッダに”BASIC ユーザ:パスワードをBase64化した改行なし文字列”を設定すると実現できます。
ステータスコードしか興味ないので、HEADメソッドでヘッダだけ取得します。
RedmineのLocationを”/redmine”していた場合、”/redmine/users/current.xml”は、ログインユーザの情報を取得するURLになります。
このリクエストに200を返せば、そのユーザは存在し、かつパスワードが有効だということになります。
SimpleHTTPは@matsumotoryさんのgist投稿から拝借させていただきました。
このようにmod_mrubyの認証機能を使うと、非常にシンプルに他システムの認証を拝借することができます。
さて、応用編はこれで終わりです。次回は実装編を書きます。