まとめ

API設計に大事なことのまとめです。

セキュリティ

ありとあらゆる攻撃を考慮しないといけません。

ユーザの環境も様々です。 APIを提供する側はそれらを制限することなんてできません。 クライアントに正しいも間違っているもありません。 不正な攻撃であろうと全てのリクエストは平等に扱われてしまうことを忘れてはいけません。

とにかく想像力が必要です。 人間は全員犯罪者で、ありとあらゆる手段を使って攻撃をしてきます。 どんな攻撃ができそうか想像し続けましょう。 単純にシステム上のやりとりだけではありません。 ソーシャルハックもかなり有効な攻撃手段です。 (ハッカーに奪われた、5万ドルのTwitterアカウント「@N」:オーナーに返還 見事なソーシャルハック事例) 他のサービスの情報と組み合わせた攻撃も有効です。 本当に穴はないですか? XSSのように機械的に検出できるようなものではありません。 複雑なシステムの一つ一つは小さな穴でも、組み合わせたら大きな穴になることもあります。 本当に穴はないですか?

とりあえずAPIの提供は必ずHTTPSを使いましょう。 経路上でおこるほとんどの攻撃はこれで防げます。 今どきはAPIだけでなく全てのWebアクセスをHTTPSにするべきです。 Google大先生に倣いましょう。

APIレスポンスの内容には十分注意をはらいましょう。 余計な情報から実装が透けて見える場合があります。 他人が知ってはいけない情報を絶対に流してはいけません。 その情報を他人が知った場合どのような攻撃に使えるか熟考して、必要な情報のみを選びましょう。 「自分のじゃない場合の個人情報はクライアントアプリで無視する」みたいな実装を提案してくるバカがいます。 死ねばいいと思います

そして何より、不要な個人情報を知ろうとしないのがもっとも効果的です。 OAuthを使えばパスワードなんか知る必要はありません。 パスワードがなければリスト型攻撃も怖くありません。 住所や電話番号を知る必要があるサービスなんてごく一部です。 知る必要のない情報は知るべきではない、というスタンスを貫くと身軽になります。

===[column] ソーシャルハック 秘密なように見えてパブリックな情報はたくさんあります。 例えば、秘密の質問によくありがちな「母親の旧姓は?」なんて家族や親戚にはノーガードです。 もちろん家族や親戚も犯罪者であることを忘れてはいけません。 田舎の場合近所のほとんどの人が知っていることもあるでしょう。 「通っていた小学校の名前は?」も全然秘密じゃないです。Facebookに書いてあります。 「飼ってるペットの名前」は積極的に出していってますよね。 「2段階認証で誕生日を入力してください」なんて完全にZALですねぇ。

人間は生きているだけで大量の情報を垂れ流しています。 垂れ流したほうがWebは面白いので積極的に垂れ流したほうがいいと思います。 個人に本物の秘密など無いとセキュリティ設計者は考えたほうがいいでしょう。 いろいろな公然の秘密と、サポートのような人間相手の交渉が組み合わさると、 システムのセキュリティは意外なほど脆く崩れ去ります。

RESTful

世の中猫も杓子もRESTfulなのでRESTfulにしましょう。 この業界、長いものに巻かれるのは大正義です。

モノをリソースとして捉え、その操作をHTTPメソッドに割り当てます。 制約を与えることで設計に統一感が出て、表現力が高まります。 当然ですがHTTPメソッドを正しく使いましょう。 GETは必ず冪等性を保証しなければいけません。

HTTPステータスコードも正しく使いましょう。 失敗しているのに 200 で返してはいけません。 JSONの中の success で判断しろなんてAPIはクソです。

最初はリソースの設計も難しいでしょう。 とことん考え、議論することが重要です。 仕事では1つのURIを決めるのに3日議論したこともあります。 それだけ名前をつけるというのは重要な行為です。

ついでに認証の方法はOAuthにしましょう。 艦これの場合、OAuth + 余計な検証になっています。 意味のない検証をやめて素直なAPIアクセスが可能であるべきです。 リファラ検証などはやってはいけません。 gzipが使えないクライアントにもきちんと対応しましょう。 世の中のすべてのブラウザを把握するなんて無理です。

JSON

大前提として、APIレスポンスとしてのJSONは人間が読むものです。 人間がもっとも理解しやすいデータ構造にするべきです。 ぱっと見ただけで意味がわかる構造になってますか? コンピュータでの処理を先に考えてデータ構造を作るとだいたい間違ったことになります。 世界を正しく認識しデータ構造をモデリングしましょう。

すべてのキー名を熟考しましょう。 全く初見でも意味が理解できるキー名になってますか? きちんとした英単語を使いましょう。 絶対に単語を省略してはいけません。 複数のものならきちんと複数形を、 状態を表す場合は形容詞がふさわしいかそれとも過去分詞かよく考えましょう。 英語力はかなり必要です。 というかエンジニアに一番必要なものは間違いなく英語力なので英語の勉強は必ずしましょう。

ただデータサイズが大きくなりすぎると、通信コストとしてジワジワ効いてきます。 可読性と通信コストはトレードオフな部分もあるので、 本当に必要であればサイズに最適化する場合もあります。

まとめのまとめ

3つに共通することはとにかく考えることです。 最近は言語やフレームワークの発達で実装に掛かる時間は大きく短縮しています。 その分とことん深く長く考えることができます。

機能が正しく動くのは当たり前のことです。 今の時代、動けば良いなんて考えは通用しません。 理解しやすいか、保守しやすいか、拡張しやすいか、 ひっくるめて如何によい設計か、というところが求められます。 どれだけアタマと時間を使ったかがAPI設計の良し悪しが決まります。 考え尽くして正しい設計を導き出すのがエンジニアの最大の使命です。

コスト

最後にすべての判断基準となるコストの話です。 システムのコスト源は

人間 > ネットワーク > (壁) > ストレージ > (超えられない壁) > CPU

であることを忘れてはいけません。 今は無限にサーバが増やせる時代なので、サーバを増やせば済むことはサーバを増やすべきです。 ストレージもちょっと高いけど無限です。 それに比べてネットワーク帯域は料金も高く、なにより通信速度に限界があり、大きなデータを送受信することはユーザ環境に依存するストレス源でもあります。

人間は最大のコスト源ですが、ここをケチると糞システムになり最終的なコストが増大します。 高コストであると同時に、最も価値を発揮する装置です。 人間はコンピュータにはできない仕事をしないといけません。 設計などの考える仕事がそれです。 実際にコードを実装する部分も、未だに機械は完全にはこなしてくれません。 良い設計から良い実装をするのもやはりまだ人間でなくてはできない仕事です。

人間がやるべき仕事をエンジニアが最高のパフォーマンスでできるということを最優先しましょう。

Last updated