簡単アクセス制限画像配信について

画像を配信する仕組みを考えたとき、
htdocsに画像を配置してしまうとだれでも好きなだけアクセスできてしまいますね。
まぁ、サイトのデザインとかで使っている素材であればいいんですが
ちょっとしたアクセス制限をかけたい素材な場合、
普通にhtdocsに配置して公開すると問題なわけです。


そういうケースの場合は今までMogileFSをつかって
ファイルを管理していたのですが、諸事情によりmogileは使わないで
管理できないかというのを考えてみました。


要件としては

  • 素材の管理で冗長構成をとらなくてよい
  • アプリ側で認めたファイルだけ提供する

です


個人的にはPerlbalを良く使っているので
Perlbalでためしてみました。


処理の流れとしては、
sv.intraがサービスを提供しているvhostでユーザはこのvhostに対して色々リクエストを投げてくるとします。
sv.intraはplackにより127.0.0.1:5000で動いているとします。
perlbalがport:80でうごいているので、sv.intraにリクエストをなげると
Perlbal127.0.0.1:5000にreverse_proxyします。
画像ファイルはPerlbalがサーブしており127.0.0.1:7000で待ち受けているとします。


sv.intraはユーザからリクエストがあれば、ユーザにその画像ファイルにアクセスしていいかどうかの判定を行い
画像にアクセスして良い場合はX-REPROXY-URLを返すとします。
Perlbalはsv.intraからうけとったX-REPROXY-URLをみて画像ファイルにreproxyする感じです。


Perlblaの設定ファイル的にはこうなります。

LOAD Vhosts

CREATE POOL intra_pool
       POOL intra_pool ADD 127.0.0.1:5000

CREATE SERVICE intra
    SET role            = reverse_proxy
    SET pool            = intra_pool
    SET enable_reproxy  = true
ENABLE intra

CREATE SERVICE http_server
    SET listen     = 0.0.0.0:80
    SET role       = selector
    SET plugins    = Vhosts
    VHOST sv.intra = intra
ENABLE http_server

CREATE SERVICE img_server
    SET listen         = 127.0.0.1:7000
    SET role           = web_server
    SET docroot        = /home/nekokak/imgs
    SET dirindexing    = 0
    SET persist_client = on
ENABLE img_server


sv.intraのコードはこんな感じです(適当です)
Perlbal::Plugin::PSGIをつかってもいいかも)

use Plack::Builder;
builder {
    sub {
        # ここで色々ちぇっくするのですよ!
        # 画像にアクセスさせてよければX-REPROXY-URLする
        return [
            '200',
            [
                'Content-Type'  => 'image/gif',
                'X-REPROXY-URL' => 'http://127.0.0.1:7000/hoge.gif',
            ],
        ];
    };
};


こうしておけば、ユーザからは画像に直接アクセスすることができず、
sv.intra経由のreproxyでのみ画像ファイルにアクセスさせることができます。
あと、PerlbalじゃなくてもX-REPROXY-URLを解釈できるものであれば(nginxとか)利用可能です。


今思いついて、試して動いたので何か問題点が他にあるかも知れませんがいい感じじゃないかとおもっています。


ユーザが画像とか素材をuploadするケースを考えるとちょっとだるいかもしれませが、
こちら側が提供する画像の配信を管理するのではつかえるんじゃないかなとおもっています。