Claris FileMaker Data API で取得したオブジェクトフィールドの参照用URLからデータを取得する上での注意点 その2

前回は、Claris FileMaker Server 上に公開されているカスタム App に Data API でアクセスして取得したオブジェクトフィールドの参照用の URL からデータをダウンロードするために、FileMaker Server の設定「 AuthenticatedStream 」を変更することで対応する方法を紹介しました。

今回は、上記の「 AuthenticatedStream 」の設定を初期値「 1 」のまま(セキュリティが強化されている状態)オブジェクトフィールドのデータをダウンロードする方法をご紹介いたします。サーバーのセキュリティ上(クラウドに公開してどこからでもアクセス可能な環境など)の理由で「 AuthenticatedStream 」の設定を変更できない方は参考にしてください。

まず、前回のおさらいですが Claris FileMaker Server 19.3.1 で強化された内容は以下の通りです。

オブジェクトデータのリクエストに FileMaker Data API が使用される場合、オブジェクトデータのストリーミングまたは表示に使用する場合に返される URL にセッショントークンが必要になることで、さらにセキュリティが向上しました。

まぎらわしいですが上記のセッショントークンとは、Data API でログインして取得したアクセストークンではありません。そうではなく、参照用の URL に初めてアクセスしたときにレスポンスヘッダで返される「 x-fms-session-key 」の値となります。

Clarsi FileMaker Server 19.3.1 でのセキュリティ対策とは、Data API にログインしてレコードから得られたオブジェクトフィールドへの参照用の URL に、初めてアクセスした利用者のみに、レスポンスヘッダにクッキーとして「 x-fms-session-key 」が返され、その値を保持してアクセスした利用者にダウンロードできるようにしたということになります。いわば、この参照用の URL は1回しか使えないようにして使い回しをできないようにしています。

ちなみにオブジェクトフィールドへの参照用の URL は以下のような形式になっています。

https://serverName/Streaming/MainDB/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.png?RCType=EmbeddedRCFileProcessor

この「xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.png?」箇所が、レコードの内容を取得するたびに毎回変わります。オブジェクトフィールドの値を取得したいときは、参照用 URL を使い回すのではなく、都度レコードの参照用の URL を取得し直してアクセスする必要があります。

オブジェクトフィールドの内容を取得するための手順

オブジェクトフィールドの内容を取得するための手順としては以下のようになります。
1,Data API で所定のアカウントでログインし、アクセストークンを取得する。
2,アクセストークンを使って目的のレコードを検索し、対象のオブジェクトフィールドへの参照用 URL を取得する。
3,参照用 URL にアクセスしてオブジェクトフィールドの内容をダウンロードする。
4,Data API からログアウトする。

注意が必要なのは、上記の 2 で取得した参照用 URL に 3 でそのままアクセスすればデータがダウンロードできるのかというとそうではなく、これまで案内した「 x-fms-session-key 」を取得して保持するような仕組みが必要という点です。

FileMaker でスクリプトを使って取得する場合

例えば、上記の 1 から 4 を FileMaker でスクリプトを使って取得する場合は以下のようにします。
1,Data API で所定のアカウントでログインし、アクセストークンを取得する。

URL から挿入
ターゲット: $json ; https://serverName/fmi/data/vLatest/databases/databaseName/sessions";
"--dump-header $$headers " &
"-X POST " &
"-H \"authorization: basic " & Base64Encode ( "user:password" ) & "\" " &
"-H \"content-type: application/json\" "
] 変数を設定 [ $token ; JSONGetElement ( $json ; "response.token" ) ]

2,アクセストークンを使って目的のレコードを検索し、対象のオブジェクトフィールドへの参照用URLを取得する。

URL から挿入 [
ターゲット: $json ;
https://serverName/fmi/data/vLatest/databases/databaseName/layouts/layoutName/records/recordId";
"-X GET " &
"--dump-header $$headers " &
"-H \"authorization: Bearer " & $token& "\" " &
"-H \"content-type: application/json\" "
] 変数を設定 [ $streamURL ;
JSONGetElement ( $json ; "response.data[0]fieldData.objectFieldName" )
]

3,参照用 URL にアクセスしてオブジェクトフィールドの内容をダウンロードする。

URL から挿入 [ターゲット: FieldName ;
$streamURL ;
cURL オプション:
"-X GET " &
"--dump-header $$headers " &
"--location " &
"--cookie-jar $cookie " &
"--cookie $cookie "
]

4,Data API からログアウトする。

URL から挿入 [
ターゲット: $json ;
https://serverName/fmi/data/vLatest/databases/databaseName/sessions/session-token";
"-X DELETE " &
"-H \"content-type: application/json\" ""
]

ポイントは、上記の 3 では cURL オプションでリダイレクトを追跡する「 –location 」オプション、レスポンスヘッダに含まれるクッキー情報を取得する「 –cookie-jar 」オプション、クッキーを送信するためのオプション「 –cookie 」を設定します。こうすることで「 x-fms-session-key 」を適切に処理してオブジェクトフィールドの内容を取得することができます。

他のプログラムで( PHP など) cURL を使ってダウンロード用のプログラムを開発する場合においても、上記のオプションを設定するようにします。

PHPの場合の記述

例えば PHP ならば上記の 3 の箇所は以下のように記述します。

■リンク元 detail.php

<a href="getfile.php?url=https://serverName/Streaming/MainDB/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.png?RCType=EmbeddedRCFileProcessor" download >ダウンロード</a>

■リンク先 getfile.php

<?php
$cookie = "";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $_GET['url']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 0);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie);
$res = curl_exec($ch);
curl_close($ch);
echo $res;
?>

参考までに参照用の URL にアクセスした場合、以下のようなヘッダ情報を得ることができます。

HTTP/1.1 302 Moved Temporarily
Server: nginx
Date: Thu, 18 Jan 2024 04:32:40 GMT
Content-Type: text/html
Content-Length: 101
Connection: keep-alive
Location: /Streaming/MainDB/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.png?RCType=EmbeddedRCFileProcessor&Redirect
Set-Cookie: X-FMS-Session-Key=0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; HttpOnly
X-FMS-Result: 0
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Access-Control-Allow-Origin: parallels-parallels-virtual-platform
Access-Control-Allow-Credentials: True
Access-Control-Allow-Headers: Content-Type,Authorization

HTTP/1.1 200 OK
Server: nginx
Date: Thu, 18 Jan 2024 04:32:40 GMT
Content-Type: image/png
Content-Length: 376983
Connection: keep-alive
Cache-Control: max-age=8640001
Accept-Ranges: bytes

はじめにアクセスすると、「 x-fms-session-key 」を含んだレスポンスヘッダが返され、そのまま HTTP/302 で所定の URL にリダイレクトされます。そしてクッキーに「 x-fms-sesion-key 」を保持してアクセスすると、HTTP/200 でアクセスに成功してデータをダウンロードすることができます。

ちなみに1度アクセスしてデータを取得した後は、「 x-fms-session-key 」が発行されないためアクセスしても以下のようなヘッダ情報が返りエラーとなります。

HTTP/1.1 401 Unauthorized
Server: nginx
Date: Thu, 18 Jan 2024 06:26:05 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 91
Connection: keep-alive
X-FMS-Result: 0
Strict-Transport-Security: max-age=31536000; includeSubDomains

まとめ

Claris FileMaker Server 19.3.1 以降のオブジェクトフィールドの参照用 URL は、1回しかデータをダウンロードできないようになっており、URL にアクセスするときも最初にアクセスしたときに返される「 x-fms-session-key 」を保持する仕組みが必要です。

再度オブジェクトフィールドの内容を取得したいときは、レコード情報を再度取得することで新たな参照用の URL が発行されるので、それを利用してダウンロードします。
ご参考下さい。