ニクニクドットミー

カッコいいおっさんを目指すエンジニアの厳かなブログ

ウェブの基礎 ヘッダーについて改めて調べてみた

いまウェブの基礎について改めて復習をしています。その過程で調べたことをブログにメモっておこうと思いました。
改めて復習をしていると「ちゃんとわかってなかったな」と気づくことが多々あり、とてもいいインプットになっています。今回はヘッダーについていくつか調べましたが、その他のヘッダーについても調べておきたいし、ウェブセキュリティ周りも復習していく予定。

Host

リクエストヘッダーのひとつ。
リクエスト先のホスト名とポート番号が記載される。
HTTP 1.1 ではHostヘッダーは必須になるが、HTTP/2では代わりに疑似ヘッダーである:authorityにホスト名とポート番号が値として入る。

例:

  • HTTP 1.1
    • Host: itdoc.hitachi.co.jp
  • HTTP/2
    • :authority: developer.mozilla.org

サーバーで VirtualHost を利用する場合にサーバーはHostヘッダーの値を判断してリクエストを振り分ける。

例えば Nginx で VirtualHost を実現するために以下のような設定を Conf に記述する。
server_nameの値とHostヘッダーの値がマッチした場合はマッチしたディレクティブが実行される。

server {
    listen       80;
    server_name  hoge.com;

    access_log  /var/log/nginx/log/hoge.access.log  main;

    location / {
        root   /usr/share/nginx/html/hoge;
        index  index.html index.htm;
    }
}

server {
    listen       80;
    server_name  fuga.com;

    access_log  /var/log/nginx/log/fuga.access.log  main;

    location / {
        root   /usr/share/nginx/html/fuga;
        index  index.html index.htm;
    }
}

ふとNginxのコードではどうなっているのか眺めてみた。読み間違いしてそうで自信はないが、Nginxのコードを眺めるきっかけになったのでよかったと思っている。

Content-type

リクエスト、レスポンスで利用するヘッダーのひとつ。
コンテンツのメディアタイプを示す。

メディアのタイプは MIME(Multipurpose Internet Mail Extensions) Type になる。 MIME はメールでテキストや画像を送るために使っている拡張仕様。
HTTP もマルチパートに対応しており、1 つのメッセージボディの中に複数のエンティティを含めて送ることができる。主に画像やテキストファイルなどのファイルアップロードの際に使われている。
マルチパートのそれぞれのエンティティの区切りとしてboundary文字列を使う。

Boundary の例

Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryxxxxyz

----WebKitFormBoundaryxxxxyz
Content-Disposition: form-data; name="Filedata"; filename="/C:/Users/xxxxx/Desktop/sample.png"
Content-Type: image/png

(data)
----WebKitFormBoundaryxxxxyz

MIME Type の例:

  • application/json
  • text/html
  • text/plain
  • multipart/form-data
    • HTML フォームを送信した場合
  • application/x-www-form-urlencoded
    • HTML フォームを送信した場合。ただしバイナリデータを扱うには向いてない。

ブラウザによっては MIME を推定し、ヘッダーの値に従わない場合もある(Content sniffing)。その場合はX-Content-Type-Options: nosniffに設定するとその振る舞いを防ぐことができる。

参照
https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Content-Type

User-agent

クライアントを示す識別子

書式
User-Agent: Mozilla/5.0 (<system-information>) <platform> (<platform-details>) <extensions>

例:

Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36

Chrome は互換性のため、KHTML, like GeckoSafari のような文字列が追加されている。

サーバー側ではUser-Agentを判定し、処理の振る舞いを変えるなどに利用する。またブラウザ以外にもUser-Agentの種類があり、ブラウザからアクセスされているのか判断することができる。
その他、GoogleAnalytics などを利用し、どのブラウザからのアクセスが多いか判断し、分析に利用することがある。

ブラウザ以外でもコンテンツにリクエストを送信するコマンドを利用した場合はそのコマンドがUser-Agentに記載される。これをウェブサーバーのログから見てなにかしらの攻撃をされているかの材料にすることもある。

  • user_agent: Wget/1.20.3 (darwin18.7.0)
  • user_agent: curl/7.64.1

参照
https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/User-Agent

accept

クライアントが処理できるメディアタイプ
例えばブラウザがimage/pngに対応していない場合、処理可能なimage/jpegimage/gifを指定する。
サーバーは提案のうち一つを選択し、それを利用してクライアントにContent-Typeレスポンスヘッダーで選択を伝える。

Accept: text/html, application/xhtml+xml, application/xml;q=0.9, */*;q=0.8

表示するメディアタイプをに優先度をつけたい場合に q 値(品質係数)を指定。0~1 の範囲(小数点 3 桁まで)の数値で1の方が高くなる。
なにもつけない場合はそれらのメディアタイプは 1.0(最高品質)を表す。

Referer

現在リクエストされているページへのリンク先を持った直前のウェブページのアドレスが含まれる。 Referer ヘッダーにより、サーバーはどこから訪問しに来たかを識別し、分析などに利用することができる。

referer: https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Accept

注意すべき点として、Referer ヘッダーに機密情報を含むウェブページのアドレスが指定された場合にリクエスト先のサーバーに情報が渡ってしまう。例えばアカウント情報のパスワードリセットリンクなどで用いられるユーザー固有の URL が Referer として渡ってしまった場合、リセットリンクが外部に漏れてしまうことにつながる。(リセットリンクに有効期限があったり、パスワードリセットの場合は既存のパスワードを求められるので不正利用がしにくい)
加えて、Referer の情報を省略するためにReferrer Policyヘッダーがある。 同じようにリクエスト先のウェブページに含まれているimgaタグに指定されている Referrer-Policy: strict-origin-when-cross-origin

  • no-referrer
    • Refere へッダー全体が省略される。リクエストとともにリファラー情報が送られることはない。
  • no-referrer-when-downgrade
    • ポリシーが指定されていない場合や値が無効な場合の規定値。プロトコルのセキュリティ水準が同一である場合(HTTP->HTTP, HTTPS->HTTPS)または改善される場合(HTTP->HTTPS)は URL のオリジン、パス、クエリ文字列がリファラーとして送信される。 低下する場合(HTTPS->HTTP)は、リファラーは送信されない。
  • origin
  • origin-when-cross-origin
    • 同一オリジン間でリクエストを行う場合はオリジン、パス、クエリ文字列を送信するが、その他は文書のオリジンのみを送信する。
  • same-origin
    • 同一オリジンにはリファラーが送信されるが、別オリジンには送信されない。
  • strict-origin
  • strict-origin-when-cross-origin
    • 同じオリジン間でリクエスト送信を行う場合はオリジン、パス、クエリ文字列を送信し、別オリジンにはプロトコルのセキュリティ水準が同じ場合はオリジンを送信し、安全性の劣る送信先にはヘッダーを送信しない。
  • unsafe-url
    • セキュリティに関係なくオリジン、パス、クエリ文字列を送信する。安全ではないオリジンへプライベートである可能性がある除法を漏洩する可能性があるので利用する場合はよく検討する。

Accept-Encoding

コンテンツのエンコーディングを示すリクエストヘッダー
サーバーは選択したエンコーディング方式をContent-Encodingレスポンスヘッダーを使用してクライアントに返す。

例:

Accept-Encoding: gzip
Accept-Encoding: compress
Accept-Encoding: deflate
Accept-Encoding: br
Accept-Encoding: identity
Accept-Encoding: *

ディレクティブ

gzip
アルゴリズム:LZ77、ハフマン符号
フォーマット:Gnu zip

deflate
アルゴリズム:LZ77、ハフマン符号
フォーマット:zlib

bzip2
特徴:deflateやgzipよりも圧縮率が高いが非標準
アルゴリズム:Burrows-Wheeler transform (BWT)
フォーマット:bzip2

brotli(br)
特徴:Googleが開発したアルゴリズム。deflateやgzipよりも高い圧縮率
アルゴリズム:LZ77、ハフマン符号、2nd order context modeling
フォーマット:brotli

identity
圧縮しない

*
ヘッダーがないデフォルト値。あらゆるエンコーディングフォーマットを指す。すべてのエンコードディングフォーマットに対応しているという意味ではない。

Nginx ではgzip:on;ディレクティブを設定することでレスポンスボディを gzip 圧縮してレスポンスを返す。

参照
CDN で WEB 高速化 コンテンツ圧縮(gzip)の設定と注意点

Authorization

ユーザーエージェントの認証情報を伝えるために使用するリクエストヘッダー
サーバーからステータスコード401を受け取った後のリクエストにAuthorizationヘッダーフィールドを含める。
Basic 認証を設定されている場合は、ブラウザは401ステータスコードを受け取った後に認証ダイアログを表示し、ID と Password の入力を求める。入力された場合は base64 エンコーディングをした上でAuthorization: Bacix xxxxxxxxxxxxxxxといった形式でリクエストを送信する。

Nginx では以下のような設定で Basic 認証を行う。

    location /basic {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
        auth_basic "Admin area";
        auth_basic_user_file /etc/nginx/.htpasswd;
    }

auth_basicディレクティブは任意の文字列を含むことができ、ブラウザによっては Basic 認証のダイアログのメッセージとして表示される。

Location

Locationヘッダーフィールドはレスポンスの受信者に対してRequest-URI以外のリソースへアクセスを誘導をする場合に使用するレスポンスヘッダー ステータスコード3xxが使用される。
リクエスト先のコンテンツが移動した場合など別サイトにリダイレクトさせたい場合に使用する。

やはり基礎を改めて学ぶのは大事だと思った😄

See you next time:)