この章では艦これのAPIのリクエストとレスポンスの共通部分を解説します。
全て http
です。
あらゆるものが丸見えです。
MitM
で認証情報を取得した攻撃者は、全てのAPIを実行可能です。
全てのAPIリクエストが POST
メソッドを使っています。
POST
メソッドは、リソースの作成に使われるべきメソッドで、
例えば艦娘のデータを取得するというAPIは、
艦娘というリソースに変化が起こらないので、 GET
を使うべきですが、
全て POST
が使われています。
ログインの際に渡された api_token
をパラメータに追加してユーザ特定を行います。
実はこれだけではなく、 Referer
ヘッダーにflashのurlを設定する必要があり、
そのurlには api_token
と api_starttime
のパラメータが付けられています。
Origin
ヘッダーにAPIサーバのドメイン、 Accept-Encoding
に gzip, deflate, sdch
の指定が必須でした。
レスポンスは全てJSONです。 正確に言うと、
svdata={JSON文字列}
という、eval
で評価すると変数 svdata
に JSON のデータが格納される javascript
のコードです。
たぶん svdata
はグローバル変数で、APIのレスポンスに対する処理は1つのグローバル変数を共有しているのではないかと思います。
文字コードはUTF-8で統一されていますが、APIのモノによってはなぜかBOM付きUTF-8になっていました。
レスポンスを出力してもBOMは目に見えないので、JSONを取得するための s/^svdata=//
が上手く動かない理由に気づきにくく、非常に困りました。もしわざとやっているならなかなか優秀な罠です。
ソースコードの保存時に起きた問題と考えられ、開発者のエディタやその設定が共通化されていないことが想像できます。 また、ファイルの先頭バイトがレスポンスにそのまま出力されている1という特徴から、 サーバの言語はphpではないか2と予想しています。
APIレスポンスのステータスコードは全て 200 OK
です。
200 OK
はリクエストが成功したことを表すステータスコードであり、
不正なリクエストや内部エラーなどでリクエストが正しく処理できない場合は、
200 OK
ではなくふさわしいステータスコードを返すべきです。
ステータスコードの代わりに、JSON 内に api_result
という情報があり、この値が 1
の場合はAPIは成功したとみなされます。
不正なリクエストや内部エラーなどでリクエストが成功しなかった場合、 api_result
は 1
以外の値になり、
このときflashクライアントは猫画面を表示します。
===[column] ねこのひみつ APIリクエストの失敗理由が(たぶん)高負荷の場合などは、 同じリクエストを続けて送ると普通に成功することがあります。 しかしflashクライアントはそれを一切することなく、ただ闇雲にリロードしろと迫ってくるのです。 艦これ最大の敵と言われる妖怪猫吊るしはこのような仕組みで提督の精神を削っていくのです。
APIレスポンスの主要なデータは、api_data
というキーの中に入っています。
大雑把に書くとこのようなデータになっています。
Github には大量のレスポンスのサンプルがあります
{"api_result": 1,
"api_data": {
"api_count": 15,
"api_page_count": 3,
"api_list": [
{"...."},
{"...."},
...
], ...
}
}
なぜか全てのキーに api_
という接頭詞が付けられており非常にデータサイズが無駄です。
レスポンスのデータサイズはそのまま通信量のサイズになり、
現代のコンピュータ環境では通信スピードが一番のボトルネックなので、
すなわちどれくらいのリクエストを処理できるかという話になります。
試しにいくつかのレスポンスから api_
の文字を抜いてみたら、データサイズが約2割削減できました。
単純に api_
を抜くだけで、通信コストや同時アクセス数、flashの負荷が約2割ほど改善されるということです。
- HTTPSを使う
- HTTPメソッドとステータスコードを正しく使う
- BOM付きUTF-8 や
svdata=
はコードからお里が知れるから削除する - データ削減を意識してレスポンスの構造を最適化する
Google先生が1バイトを削るのに心血を注いでいるように、 レスポンスを1バイト削ることは積み重なって大きな改善になります。 個別のレスポンスを見ていくと、酷いデータ構造もたくさんあり、 データ量の削減を意識してデータ構造を再設計するとかなり負荷は改善されると思います。
Footnotes
- ↩
-
テンプレートに紛れ込んでいる可能性もあるがJSONを個別にテンプレートファイルに書くとは思えない ↩