[IM]MediaAccessクラスと新たな拡張点(2)

こちらの文書の続きです。

FileMakerのオブジェクトフィールドを参照する

オブジェクトフィールドはデータベースごとに扱いが異なり、統一的にはやりにくい処理ではあります。MediaAccessクラスでは、FileMaker Serverをターゲットにオブジェクトフィールドに対応する機能を作成しました。

FIleMakerはFXを経由し、XML共有の仕組みを使います。テキスト型や数値型は、基本的にテキストでフィールドにあるデータが得られます。一方、オブジェクトフィールドはオブジェクトそのもののデータではなく、フィールドのデータに応じた以下のような「テキスト」が得られます。

/fmi/xml/cnt/photo.jpg
http://server:16000/…

PDFは完全なURLで、FileMaker Serverに16000ポートで接続して取り出すことが可能です。JPEGなどの画像の場合は、URLのパスに相当するものが得られますが、たとえばIMGタグのSRC属性にそのまま指定が可能な文字列になります。

いずれにしても、両方ともURLであると解釈すればいいわけです。この仕組みはFileMaker Serverに限らず、一般的なアクセスにも使えます。つまり、media=URLと指定をした場合は、そのURLにアクセスしたデータをMediaAccessクラスが取得し、さらにクラスを呼び出した元にそのデータを返します。/fmi/xml/cntで始まる物だけは特別にURLであるという処理が組み込まれています。また、URLかどうかはそれ以外には、httpあるいはhttpsで開始するものかどうかで判定しています。

MediaAccessでのアクセス権

認証が成立したらすべて参照可能となり、成立しなければ参照不可という単純なものなら非常に話が早く、前に説明したmedia-tokenの仕組みで事は足りるのです。なお、データはCRUDの4つの側面がありますが、メディアに関しては「編集」というのはWeb世界ではかなり難易度が高い世界であり、MediaAccessクラスはほぼ参照のみのサポートになっています。

ここで、メディアそのものがログインしたユーザごとのアクセス権を持たせたい場合が出てきます。レコードについては、特定のフィールドにユーザ名やグループ名を入力することで、そのユーザやグループに所属したユーザでないと参照や更新ができない仕組みを持っています。フィールドのデータはそれでいいのですが、メディアは実体はレコードと別に有ります。ここで、個々のメディアをコンテキストのレコードと結合させ、レコードごとのアクセス権をメディアにまで及ぼす仕組みを組み込みました。

まず、IM_Entry関数の2つ目の引数(オプション引数)に、キーが’media-context’で値がコンテキスト名(コンテキストのnameキーに対する値)を与えます。すると、メディアはこのコンテキストにある特定のレコードの、1つのフィールドのようなふるまいになります。

‘media-context’ => ‘context-name’,

実際にメディアにアクセスするパスは次のような形式にします。つまり、コンテキスト名、レコードの検索条件をパスに入れます。最初のfilesは特に意味はなく、相対パスの最初のキーワードです。context-nameは、media-contextの値と同じでなければなりません。そのコンテキストのkeyキーに対する値、つまり主キーがpidであるなら、たとえば、field=valueは、pid=312 のような値になります。

context.php?media=files/context-name/field=value/filename.png

ここでもし、media-root-dirが /var/www/media であるなら、実際に

/var/www/media/files/context-name/pid=312/finename.png

という絶対パスの画像ファイルが存在する必要があります。コンテキストの定義には、レコード単位のアクセス権設定があれば、メディアに対するアクセス権の認証の確認を行い、ユーザを特定します。pid=312のレコードがそのユーザにアクセス権があるのかどうかを確認することによって、アクセスの可否を決めます。従って、適当にpid=316などとパスを変えても、その条件で検索されたレコードが他のユーザに対する権利があるものであれば、400番台のレスポンスを返してデータは返しません。認証の確認を行い、そのユーザに対するアクセス権がないものは出力しないという仕様によりアクセス権は定義した通りに適用されます。

pid=312を、age=45のようにできると言えばできますが、おそらく、そういうディレクトリは存在せず、漏洩にはならないでしょう。

ファイルのアップロードのコンポーネントは、コンテキスト名やレコード検索条件のパスを自動的に作成するようにも作られています。

とまあ、ここまで書いたところで、ソースに間違いを発見! また、グループ名をフィールドに入れる場合はまだ実装していなかったことも思い出しました。今のところ、メディア関連処理は、開発している側で「必要の合った」状況しかうまく動かない可能性があります。ぜひとも、いろいろ試してフィードバックをください。

(まだ続く)

[IM]MediaAccessクラスと新たな拡張点

INTER-Mediatorはデータベースの内容を取り出し、Webページに展開し、場合によっては書き直したデータをデータベースに書き戻します。この一連のDBを中心としたデータの流れがあるのですが、Webアプリケーションではこれだけではすべてはまかなえません。HTMLでページを作るときは写真などの画像を別のファイルで供給します。このHTML外に実データが存在するようなものを「メディア」と呼ぶことにします。

メディアにはいろいろな種類があります。主要なものはIMGタグ要素で表示する画像、OBJECTタグなどで表示するFlashのコンテンツやビデオなど、そしてリンク先で得られるものとなるでしょうか。また、それぞれ、サーバ上にスタティックにあるものや、データベースのオブジェクト型フィールドに存在する場合もあります。WebページからこれらにアクセスするためのものがMediaAccessクラスです。概ね、次のような用途に使用方法は分類できます。

  • サーバ上にある画像ファイルを参照する
  • FileMakerのオブジェクトフィールドを参照する
  • データ生成を指定したクラスにさせる、生成結果を返す

ここで、単なる画像は普通にHTMLを書けばいいじゃないかと思うかもしれませんが、MediaAccessクラスを使う理由は、認証やアクセス権の設定との連携が可能になっているところです。

サーバ上にある画像ファイルを参照する

スタティックな画像で、認証が絡まない場合は、普通にIMGタグを記述します。また、画像ファイル名やパスがデータベースにある場合でも、必ずしもMediaAccessクラスは必要ないかもしれません。たとえば、あるテーブルのfilepathフィールドにファイル名が記録されているのなら、このようなIMGタグで表示できるでしょう。#srcにより、この要素のSRC属性にフィールドのデータが追加されます。

<img src=”figs/” class=”IM[context@filepath@#src]” />

ページの内容を認証しなければ参照できないようにしたとき、やはりページに埋め込んだ画像なども認証を経由したいと考えます。Webサーバレベルでの認証の場合は、ある意味、認証がない場合と概ね同じことで可能ですが、INTER-Mediatorの認証機能を使った場合、SRC要素がスタティックな画像を参照していれば、もしかしたら、認証しなくても画像だけは見えてしまうかもしれません。そんなことをしても大した情報流出にならないとも言えるのですが、ガードしたいものはガードするのが基本ですし、認証しているのに一部は誰でも見えるのは正しい運用ではありません。

そこで、IM_Entry関数の2つ目の引数(つまりオプション引数)に、’media-root-dir’というキーで、サーバ上にあるメディアファイルのフォルダへのルートからの絶対パスを指定しておきます。たとえば、

‘media-root-dir’ => ‘/var/www/images’,

となっていたとします。あるページファイルで使われている定義ファイルのパスがcontext.phpだったとします。すると、次の部分URLが、メディアを返します。ここで背後では、MediaAccessクラスが使われており、このクラスがメディアに対するプロキシになっているとも言えます。

context.php?media=ch1/shot345.png

たとえば、IMGタグのSRC属性に上記のURLを記述すれば、media-root-dirと合成して、「/var/www/images/ch1/shot345.png」というファイルをアクセスし、その内容を取り出して、適切なMIMEタイプのヘッダとともに出力をします。

前記のURLにある画像ファイル名「shot345.png」がフィールドpicfileにあるような場合には、ページファイルの要素には以下のような記述ができます。media=は決められたキーワードです。

<img src=”context.php?media=ch1/” class=”IM[table@picfile@#src]” />

このとき、定義ファイルで認証が必要な設定になっていると、SRC属性のURLからの取得時にMediaAccessクラス内部で、認証の確認を行います。ここで、一般の認証時に使っているクレデンシャルをそのまま使うことが実はできません。一般の認証では、1つのアクセスごとに異なるチャレンジデータを使うことで、認証の乗っ取りをしにくくしています。しかし、そのためにメディア処理ではその仕組みが使えません。なぜなら、メディアへのアクセスは並列的にブラウザから行うからです。

そこで、メディアアクセス時の認証のためだけのクレデンシャルを生成させるようにしています。たとえば、直前のimgタグ要素の場合、tableという名前のコンテキストからの取得となりますが、そのコンテキスト定義(IM_Entry関数の第1引数)の’authentication’キー内部の’media-handling’キーの値をtrueにします。すると、このコンテキストのデータを取得するときに、サーバ側からメディア用のクレデンシャルを出力します。

IMGタグ要素などから実際にメディア取得を定義ファイルに対して行うとき、media=があれば、MediaAccessクラスに処理をまかせます。そのとき、クレデンシャルがクッキーに記録されてサーバ側に到達し、それを発行したクレデンシャルと比較することで認証が通っているかどうかを判定します。つまり、コンテキストが得られるということは認証が通っているわけで、その信頼関係をもとに秘密の合い言葉をやりとりします。このクレデンシャルは繰り返し使われる可能性があります。クッキーに記録し、時間が来れば消去するようにはなっているものの、クレデンシャルを盗まれるのはそれだけでメディアアクセスを可能にしてしまうことになります。従って、HTTPS(SSL)でのサーバ運用は必須とも言えるでしょう。

普通のHTMLでMediaAccessを経由させる

Webページを作って画像を埋め込むと、<img src=”img/cover.jpg” /> などと記述します。これをMediaAccessクラスを使ってデータの取り出しを行いたいとしたら、ソースを全部変更しないといけないのかというとそうではありません。リダイレクトを使うことで、HTMLソースはそのままに、MediaAccessクラスを使うことができます。たとえば、.htaccessファイルを作り、たとえば次のような記述を作ります。

RedirectMatch img/(.+) http://host.name/myapp/context.php?media=$1

すると、<img src=”img/cover.jpg” /> は、<img src=”http://host.name/myapp/context.php?media=cover.jpg” /> と同じことになるわけです。

部分パスと絶対パス、それらを消したり追加したりといろいろ複雑にはなりますが、このスタティックなメディアを認証した上で表示できるようにしたのがMediaAccessの最初のインプリメントでした。

(この内容、続く)

Booking.comを騙るメール

来ました。予約した覚えはないのですが、1泊で1800ドルとはゴージャスなものです。ただ、よくあるタイプの別のサイトへの誘導は明示的ではなく、HTML内にあるのリンクはちゃんとbooking.comに行きますね。しかし、金額は書いてあるけど、どこのホテルか書いていない。そんな予約はありえないでしょう。このメールアドレスで昔booking.comを使った可能性もあるのですが、なんとアカウントは作られていませんでした。まあ、これでほとんど安心なのですが、念のためアカウントを作ってみたのだけどやはり予約は入っていません。また、添付するzipを展開するとexeが入っていたので間違いなく、嘘メールでしょう。あと、巧妙なのは、本物のBooking.comの広告メールと同じような時間に配布しているところですね。

だけど、ClamXavだとマルウェアと判定はしませんでした。Booking.comには似たような警告はありますが、このメールではなく、1年ほど前の別のもののようです。ということで、警告の意味も含めてブログに記載します。1ヶ月ぶりの書き込みがこんな話題ですんません。

スクリーンショット 2013-08-06 14.52.52 スクリーンショット 2013-08-06 14.53.09