Authorization

「ここ最近最も大胆な手口の銀行データ盗難」などと言われたこの事件、大量の顧客情報を盗んだ手口は驚くほど単純なものだったそうだ。なんとシティグループのウェブサイトのクレジットカード顧客が利用するページのURLには顧客の口座番号が埋め込まれていたそうで、犯行グループは単にこの番号を他の番号に置き換えていくことでデータを手に入れていたとのこと。犯行グループはこの口座番号を入れ替えてデータを取得するプログラムを開発し、大量のデータを持ち逃げしたとのことだ。

口座番号がURLに埋め込まれているのが問題であるかのような書き方だけど、問題なのはリソースへのアクセスコントロールができていない事だよね。とはいえ、さすがに口座番号みたいな際どい情報をURLに入れる勇気は無いな。こういう場合は無難にサロゲートキーを使った方がいいと思う。

もっとも、サロゲートキーだろうが口座番号だろうがアクセス制御ができてなければ結果は同じ。RailsはURLでリソースのIDを指定してRESTfulにリソースにアクセスするのが基本だが、IDが連番で生成され、容易に推測可能なため、きちんとアクセスコントロールをしないと簡単に他人のリソースを覗ける糞アプリができ上がる。さくっと単体テストで他人のリソースにアクセスできない事を確認すべき。

ところで、http://example.com/hoges/1 のようなURLで他人のリソースにアクセスしようとした場合、自分は403より404を返すように書くことが多い。そのリソースへのアクセス権限がない(403)ではなく、アクセス可能なリソースが存在しないと解釈して404 Not Found。

403の場合

@hoge = Hoge.find(params[:id])
if @hoge.nil?
  # 404レスポンスを返して終了
end

if @hoge.user_id != @current_user.id
  # 403レスポンスを返して終了
end

404の場合

@hoge = Hoge.where(:id => params[:id], :user_id => @current_user.id).first
if @hoge.nil?
  # 404レスポンスを返して終了
end

この辺はプログラマの趣味が出てくる場面だと思うけど、どっちの方がより良いのだろうかね?