Web 業界 1 年目が Web を支える技術を読んだ感想
読んだ経緯
今年から Web 業界の企業に入社をして、日々奮闘しているのですが基本的な Web の知見が足りておらず話についていけないと感じる場面がありました。そこで Web の基礎を養おうと思いこの本を読むことにしました。
Web を支える技術についての詳細はこちら
学びや気づき
簡潔な URI を設計しリンク切れを未然に防ぐ
以下の要素を含む URI の設計にしてしまうと、将来リファクタリング等で影響範囲に入ってしまい、URI を変更しなければならなくなる
- プログラム言語依存の拡張子を利用する(.pl,.rb など)
- 実装依存のパス名を利用する(servlet など)
- セッション ID を利用する
変わらない URI を「クール URI」という。
ステートフルとステートレス
クライアントとサーバー間のやり取りには「ステートレス」と「ステートフル」という2つの性質がある。
この2つの性質を端的にいうと、
前回のやり取りを保存しておいてその内容を処理結果に反映させる仕組みを「ステートフル」、前回のデータを保存せず処理結果に反映させない仕組みを「ステートレス」という。
本書でとてもわかりやすい例があったので下記に示す。
ハンバーガー屋でのやり取り(ステートフル)
客:ハンバーガーセットをお願いします。
店員:サイドメニューは何になさいますか。
客:ポテトでお願いします。
店員:ドリンクは何になさいますか。
客:コーラでお願いします。
店員:かしこまりました。
ハンバーガー屋でのやり取り(ステートレス)
客:ハンバーガーセットをお願いします。
店員:サイドメニューは何になさいますか。
客:ハンバーガーセットのサイドメニューはポテトでお願いします。
店員:ドリンクは何になさいますか。
客:ハンバーガーセットのサイドメニューはポテトでドリンクはコーラでお願いします。
店員:かしこまりました。
上記を見るとやり取りに関してステートフルは簡潔でステートレスは冗長であることがわかる。
一見、ステートフルの方が良さそうに見えるがそれぞれにメリットデメリットがあり、
ステートフルは1回のリクエスト量が少なくて済むがリクエスト数が多くなるとデータの同期するオーバーヘッドが無視できなくなりスケールアウトが難しく、
ステートレスは全ての情報をリクエストに含ませないといけないが、サーバ側は全てのやり取りに対して覚える必要がないためスケールアウトがしやすいという特徴がある。
HTTP は「ステートレス」な性質を持っている。
べき等性と安全性
HTTP のメソッドは用件によって使い分けられているが、それぞれのメソッドにおいて「べき等」と「安全」
の性質の有無がある。
「べき等性」とはある操作を何回行っても結果が変わらないことを指し、「安全性」とは操作対象のリソースの状態を変化させないことを指す。
以下は各主要 HTTP メソッドに対応する性質を示す。
メソッド | べき等 | 安全 |
---|---|---|
GET | ○ | ○ |
PUT,DELETE | ○ | × |
POST | × | × |
GET は単に取得だけであるので、「べき等性」、「安全性」どちらも有していることは想像つきやすい。
PUT、DELETE は「べき等性」はあるが、「安全性」はない。べき等性があり、安全性がないというのは
1回目のリクエストの成功が確認できなくとも再度実行し処理が実施できれば結果として変わらないということ、または1回目成功を確認した後に
再度実行をしても結果としては変わらないということを意味している。
POST はロジックを伴う処理をリクエスト値を用いて算出したりしているため「べき等性」、「安全性」どちらも持ち合わせていない。
上記のように HTTP メソッドはそれぞれで性質を持ち合わせている共通認識があるため、性質に合わせた実装を心がけることで安全な設計をすることができる。
認証
よくある ID,PASSWORD を使ったログインのようなアクセス権限を検証するための手段。
現在では「Basic 認証」、「Digest 認証」の二つがよく使われている。
- Basic 認証
ユーザー名とパスワードによる認証方式。ユーザ名とパスワードを「:」で連結したものを Base64 エンコーディングで暗号化して Authorization ヘッダに入力して送信をする。
Base64 エンコーディングは暗号化ではなくエンコーディングであるため実質平文でユーザ名とパスワードを送信していることと同義(復号が可能)であるため、Basic 認証を単体で使用するかはセキュリティの観点から要検討すべきである。
例
GET /example HTTP/1.1
Host: sample.jp
Authorization: Basic dHUHFKksadf34asdfh==
<!-- 「dHUHFKksadf34asdfh==」を復号すると「ユーザ名:パスワード」になる -->
- Digest 認証
ハッシュ関数を用いて Basic 認証よりも強固な認証方式。ハッシュ関数はある文字列を入力した時に複雑な文字列を算出して返すもので同じ入力に対して必ず同じ文字列で返ってくる関数である。
Digest 認証の流れはクライアントが認証情報なしでリクエストを送り、それに対してサーバ側は認証失敗と共に有効期限を示すタイムスタンプ、サーバー側が持つパスワードから「nonce」と呼ばれるワンタイムパスワードと Digest の生成方法を示す「qop」(詳細は割愛)などを返し、それらを元に再度認証情報を含んだリクエストを送信し、権限の有無を検証し結果に合わせたレスポンスを返す流れになっている。
Digest 認証はユーザ名とパスワードが暗号化されているが内容が平文で送られるため内容も暗号化する場合は HTTPS を併用した方が良い。
Digest 認証の流れ
- クライアントが認証情報無しでリクエストを送る。
- サーバーは認証失敗と共に認証情報に必要な情報を含ませてレスポンスを返す。(この時のヘッダの情報を「チャレンジ」という)
- クライアントはユーザ名、realm(名前空間)、パスワードを「:」で連結して、ハッシュ値(MD5)を求める
- 続けてクライアントはメソッドと URI のパスを「:」で連結し、ハッシュ値(MD5)を求める。
- さらに続けてクライアントは「nonce」と「nonce を送った回数」,「クライアントが生成した nonce」、「qop」、前段の 3 と 4 で生成した文字列を「:」で連結してハッシュ値(MD5)を求めてリクエストを送る。
- リクエストを受け取ったサーバーは自身でも同じ方法でハッシュ値(MD5)を算出して、同じ文字列になるか認証をする。
本を読んだ感想
HTTP における基本的なメソッドの種類やヘッダー、ボディの構成が歴史的背景に基づいて段階的に説明をされていたので初学者に対してとても参考になる技術書であると感じました。
IF 設計についての考え方もとても詳しく記載されていましたので、読んだ後も実践経験と照らし合わせて再度読み返すことで違った気づきが得られるなと感じました。今後はリソース設計に関してもっと詳しく書かれている技術書を読んでみたいと考えています。