devdevdevReports

dev系開発開発者の開発日記

【WEBを支える技術】HTTPヘッダ編~~

Webを支える技術 -HTTP、URI、HTML、そしてREST (WEB+DB PRESS plus)

Webを支える技術 -HTTP、URI、HTML、そしてREST (WEB+DB PRESS plus)

  • 作者:山本 陽平
  • 発売日: 2010/04/08
  • メディア: 単行本(ソフトカバー)

HTTPヘッダの重要性

  • メッセージボディに対する付加的な情報(メタデータ)を表現
  • クライアントとサーバはヘッダを見てメッセージに対する挙動を決定する
  • メディアタイプなや言語タグなど、アプリケーションのフレームワークでなく、実装者が設定するヘッダも多い

HTTPヘッダの生い立ち

  • HTTP1.0から登場
  • 電子メールのメッセージ仕様のヘッダ形式をもとに追加
    → インターネットの成長とともに規定された歴史
  • HTTP1.0から登場ヘッダと電子メールのメッセージヘッダと共通部分が多い
    例)Content-Type、Dateなど

  • 歴史からくる制約、バッドノウハウも多い

    • メール:7bit ASCIIコード以外の文字が入れられない
    • HTTP:文字エンコーディングの制限でラテンアルファベット以外い入れられない
  • 電子メールとの違い

    • メール
      • 1方向にしかメッセージのやり取りができない
    • HTTP
      • 一度の通信でリクエスト/レスポンスの2つのメッセージをやりとり

日時

MIMEメディアタイプ

  • メッセージでやり取りするリソースの表現の種類を指定
  • 電子メールからきた仕様(Muktipurpose Internet Mail Extensions)

  • Content-Type

    • メディアタイプを指定する
    • タイプとサブタイプで構成
  • charsetパラメータ

    • 文字エンコーディングを指定する。
    • タイプがtextの場合、デフォルトがISO8859-1のため日本語だと文字化けする。
    • xmlの場合だと、xmlの中に文字コードを定義してもHTTPヘッダで定義しておかないと、文字化けしてしまう
    • 必ずcharsetパラメータを定義したほうがいい。

言語タグ

  • Content-Language
    • リソース表現の自然言語を指定する
    • ISO639で定義された言語コードとISO3166で定義された地域コードを指定
      例)「ja-JP」

コンテントネゴシエーション

  • メディアタイプ、文字エンコーディング、言語タグはサーバーで指定
  • クライアントと交渉して決めることができるパラメータ

  • Accept

    • 処理できるメディアタイプを伝える
    • メディアタイプに優先順位をつける
    • サーバーがクライアントからの要求にこたえられない場合、「406:Not Acceptable」
  • Accept-Charset

  • Accept-Language

    • 処理できる言語を伝える
    • 自然言語に優先順位をつける

Content-Lengthとチャンク転送

  • Content-Length

    • ボディの長さを指定する
    • 静的ファイルなどあらかじめサイズがわかっている場合
  • Transfer-Encoding:chunked

    • チャンク転送
    • ボディを分割して転送する。
    • 動的に画像生成する場合など、ファイルサイズが決まるまでレスポンスが返せない場合に応答性能が低下するのを防ぐ
    • チャンクサイズは16進数を仕様
    • HTTP1.1で受信が必須仕様

認証

  • HTTP認証方式

    • リソースへのアクセス制御がかかっている場合のクライアントへの認証情報通知
    • ステータスコード
      • 401 Unauthorized
      • このリソースに対してのアクセスには認証が必要
    • WWW-Authenticateヘッダ
      • 認証方式
      • URI空間
         →URI中にあるパス以下のコト
      • 同じURI空間に属するリソースには同じ認証情報を送信できる
  • HTTPS

    • HTTP、SSL/TLSを組み合わせた通信の総称
    • 通信路を暗号化して通信データを保護し、盗聴を防ぐ目的で利用する
      • 暗号化
      • 認証
      • 改ざん検知
  • Basic認証

    • ユーザー名とパスワードをAuthorizationに入れれてリクエス
    • ユーザー名とパスワードは「:」で連結し、Base64エンコーディング
    • 簡単にデコード可能なので、平文がネットワーク上に流れている
    • 許容されるセキュリティ強度か、HTTPS通信(SSLTLS)で暗号化するなどの検討が必要
  • Digest認証

    • セキュアな認証方式
    • 認証なしでリクエストして、レスポンス情報から認証情報を生成し、再送信する
    • チャレンジ

      • リクエス
        • 認証情報なし
      • レスポンス
        • nonce

          • number used once
          • リクエストごとに変化する文字列
          • タイムスタンプ、パスワード(サーバーのみが知りえる情報)などから生成
          • 有効期間を狭めるためにタイムスタンプを活用
        • qop

          • quality of protection
          • 「auth」 or 「auth-init」が指定
          • クライアントのメッセージダイジェスト作成方法に影響あり
          • auth:メソッドとURIからメッセージダイジェストを作成
          • auth-init:メソッドとURI、メッセージボディからメッセージダイジェストを作成
          • POSTやPUTの場合、メッセージ全体が改ざんされていないことを保証
        • opaque

          • クライアントが推測できない文字列
          • URI空間ごとに共通
    • 再送信

      • ①ユーザー名、realm、パスワードパスワードを「:」で連結し、MD5ハッシュ値を求める
      • ②メソッドとURIのパスを「:」で連結し、MD5ハッシュ値を求める
      • ③①、サーバーから得たnonce、クライアントかがnonceを送った回数、クライアントが生成したnonce、qopの値を「:」で連結し、MD5ハッシュ値を求める
        • リクエストのHTTPヘッダのresponseに③を入れて、再送信する
    • 利点

      • パスワードに関するセキュリティリスクを低減
        • パスワードを盗まれる危険性がない
        • パスワードそのものを預けなくてもよい、パスワードのハッシュ値を保管すだけ
    • 欠点

      • パスワード以外のセキュリティリスクは回避できない
        • パスワードのみを暗号化
        • メッセージ自体は平文でネットワーク上に流れる
      • クライアント側の負担が大きい
        • 同じURI空間でも毎回チャレンジして、ダイジェストを生成する必要がある
          (nonceを取得するため)
    • 普及していない理由

      • クライアント側の負担が大きい
      • ApacheなどのWEBサーバーではDigest認証がオプション扱い
      • ホスティングサービスではサポートされていない可能性が高い
      • 自前で用意する場合もセキュリティ上の問題でApacheがヘッダーを渡してくれないため、Digest認証を利用できない
  • WSSE

    • HTTP1.1の標準外の認証方式
    • AtomPubやWEBAPIの認証で利用
    • Basic認証やDigest認証が利用できない場合にパスワードをネットワーク上に 流さずに認証するために誕生
    • WS-SecurityのUsernameTokenがベース
    • 方式

      • クライアント側

        • クライアントが認証情報なしでリクエス
        • クライアントがリクエストを再送信
        • AuthorizationヘッダにWSSE、profileにサーバから受け取ったUsernameTokenを設定
        • X-WSSEにパスワードダイジェスト、nonce、日時情報を設定
      • サーバー側

        • サーバーが401 Unauthorizedを返却
        • WWW-Authenticateにprofileを設定(UsernameToken)
        • サーバーがクライアントのパスワードダイジェストと比較して認証
    • サーバー側でパスワードを保存する必要がある

    • パスワードがネットワーク上に流れることはない
    • Basic認証とDigest認証の中間

キャッシュ

  • サーバから取得したリソースをローカルストレージに蓄積し、再利用する手法
  • ローカルストレージにキャッシュしたデータそのものをキャッシュと呼ぶこともある

  • ヘッダ(サーバーへのアクセスをしない)

    • Pragma

      • キャッシュを抑制
      • 「no-cache」のみ指定可能
      • 指定された場合は必ずサーバーにアクセスする
      • キャッシュを抑制させない場合に指定(Cache-Controlにも指定)
    • Expires

      • キャッシュの有効期限を示す
      • クライアントが有効期限内からサーバーへのアクセスを行うか判断する
      • 最長1年を推奨
      • 有効期限が明確に決まっている場合に指定
    • Chache-Control

      • 詳細なキャッシュ方法を指定する
      • HTTP1.1で追加、Pragma、Expiresを代用可能
      • 相対的な有効期限設定が可能
      • 有効期限が相対的に指定したい場合に指定
  • 条件付きGET

    • サーバーに判断してもらう
    • クライアントではキャッシュ利用不可と判断された場合でもリクエストヘッダに情報を詰めて、キャッシュ利用可否をサーバーに判断してもらう

    • if-Modified-Since

      • リソースの更新日時を条件にする
    • if-Non-Match

      • リソースのEtagを条件にする
      • サーバーがEtagを出している場合に利用、正確な更新有無が判断可能
    • 静的ファイルの場合

      • Webサーバーで判断可能
      • inode番号、ファイルサイズ、更新日時から自動計算可能
    • 動的リソースの場合

      • アプリケーションで判断する
      • 生成したHTMLなどからEtagを算出
      • サイズが大きなリソースや複雑なクエリが発生する場合はメタデータで生成、リソースの更新カウンタから算出

持続的接続

  • HTTP1.1からの追加機能
  • 問題

    • リクエストレスポンスのたびにTCPコネクションの確立、切断を繰り返していた
       →処理が重くなっていた。画像や外部ファイルが多いWebページだととくに
  • 解決

    • 都度接続、切断を繰り返すのではなく、接続し続ける手法が開発
    • HTTP1.0ではオプション(keep-alive)
    • HTTP1.1ではデフォルト
    • パイプライン化
      • クライアントはサーバからのレスポンスを待たずに同じサーバーにリクエストを送信可能
    • コネクションを切断したい場合、(Connection:close)を指定

その他のHTTPヘッダ

  • Content-Disposition
    • サーバがクライアントにファイル名を提示
    • 電子メール仕様から伝承
    • 文字エンコーディングが必要

まとめ

【WEBを支える技術】を読む理由 - devdevdevReports

【WEBを支える技術】REST編 - devdevdevReports

【WEBを支える技術】URI仕様編 - devdevdevReports

【WEBを支える技術】URI設計編~良いURI設計とは~ - devdevdevReports

【WEBを支える技術】HTTP基礎編~シンプルさが標準化~ - devdevdevReports

【WEBを支える技術】HTTPメソッド編~名は体を表す~ - devdevdevReports

【WEBを支える技術】HTTPステータス編~名は体を表す~ - devdevdevReports