sinatra-authenticationをPassenger / Sequel / MySQL環境で使う
Sinatraで書いているwebアプリに認証機能が必要になったので「sinatra-authentication」を使ってみたメモ。
概要
Rubyでwebアプリを書くのに大人気のSinatra。でもweb開発で必要になる機能ってどんなフレームワークでもあんまり変わらないので、そのうち「認証機能が必要だよね」なんてことになる。
最初はRack::Auth::Basicを使っていたのだが、ユーザの追加 / 変更が面倒だったり、どうも挙動が不安定だったり(一定時間ログインできなくなるという謎の不具合が出たり)したので、他のライブラリを検討してみた。
自分でこんな感じのものを作ろうかなーとも思ったのだが、まずはあるものを使ってみよう、ということで「sinatra-authentication」を導入してみた。
環境
- CentOS 5.4
- MySQL 5.1.47
- apache 2.2.14
- ruby 1.9.1 p378
- rack 1.2.1
- passenger 2.2.14
- sequel 3.13.0
- ruby-mysql 2.8.1
- sinatra 1.0
- sinatra-authentication HEAD (0.3.2 159149)
- rack-flash 0.1.1
- haml 3.0.16
ポイント
- SinatraのアプリケーションクラスはSinatra::Baseを継承する「Modularスタイル」を使おう。
- sinatra-authenticationはtrunkの先端を持ってきている。sequel対応したものはまだgem化されていない(2010-08-10現在)。ドキュメントやサンプルがないのでちょっと手探りが必要だった。
- use Rack::Flashはセッション開始後に記述する。
- Sequel::Modelは利用時にSequel.connectでDB接続が要求される。
- 拡張モジュールを使うにはクラス定数をregisterする。
- lib/models/sequel_user.rbに認証用テーブルのmigrationが書いてあるのだが、MySQLではこのまま通らない。:unique => trueなのでUnique Indexが作成されるのだが、MySQLではTEXT型につけるindexに長さを指定する必要がある。Sequelでの指定方法が見つからなかったので、とりあえず定義を書き換えてしのいでいる。あらかじめtableを作成しておいてもok。
- extended_views/signup.hamlには使われていない「user_name」というinputが定義されている。これがあるとSequelがsaveに失敗する(カラムがないから当然)ので、フィールドを削除しよう。
- その他細かい解説はソースコードにコメントしておいた。
ソースコード
sinatra-authentication / lib / models / sequel_user.rb
# String :email, :unique => true, :text => true
String :email, :unique => true, :size => 255 # こっち
app.rb
# -*- encoding: utf-8 -*-
require 'sequel'
require 'sinatra/base'
require 'haml'
# Sequel::Modelは呼び出し時にDB接続を要求する。
# lib/sequel_user.rbでDBを要求するので、接続してからrequireする必要がある。
DB = Sequel.connect "mysql:://#{username}:#{password}@#{host}/#{database}"
require 'sinatra-authentication'
require 'rack-flash'
class MyModule::MyApp < Sinatra::Base
register Sinatra::SinatraAuthentication # 拡張モジュールとしてSinatraAuthenticationを使用するよ
# sinatraお決まりの設定
set :public, File.join('path', 'to', 'public')
set :views, File.join('path', 'to', 'views')
# sinatra-authentication付属のテンプレートを置いたパスを指定
set :sinatra_authentication_view_path, File.join('path', 'to', 'views', 'extend_views/')
# セッションの寿命と暗号化キーを指定
use Rack::Session::Cookie, :expire_after => 3600, :secret => 'change_me'
# Rack::Flashの使用宣言 / use Rack::Session のあとに記述すること
use Rack::Flash
get '/' do
login_required # 認証が必要なルート -> 失敗するとログインフォームへ
haml :index # 認証が通ればこっち
end
end
config.ru
# -*- coding: utf-8 -*-
require ::File.join 'path', 'to', 'app'
use MyModule::MyApp
run Sinatra::Base
まとめ
sequelへの対応がわりと最近されたので、まだ全然落ち着いていない感じのライブラリであるが、ハマりポイントさえ押さえておけば手早く認証機能が作れて、簡単な権限管理までついてくる。IDはメールアドレスを想定してバリデートしちゃうとか、facebook対応がついてきちゃうとか、いろいろツッコミどころはあるが、試してみてはいかがだろうか。