Content-Type と Content-type と content-type どれが正しい

色んなドキュメントを見たりしていると、タイトルのように複数の大文字小文字のパターンがありどれならいいのか混乱したので少し調べた「メモ」です。

rfc7540#section-8.1.2の辺りを見ました。

  • HTTP1.1 では大文字小文字区別しない
  • HTTP2 では大文字は駄目で、小文字である必要がある?

とのことです。

なので多分content-typeを使っていけば問題ないのかなということで、小文字を使っていこうと思いました。

オリジン間リソース共有 (CORS)

いつか書く。

Access-Control-Allow-Origin

通信許可できる参照元オリジン名。

Access-Control-Allow-Methods

この通信で許可できるメソッド GET, POST, OPTIONS, PUT, PATCH, DELETE

Access-Control-Allow-Headers

通信時にヘッダーに含めても大丈夫な項目。

Access-Control-Allow-Credentials

クッキーをやり取りするかどうか。する場合はtrueを指定します。

エラー

Access to fetch at 'APIのURL' from origin '送信元origin' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header has a value '送信元origin' that is not equal to the supplied origin. Have the server send the header with a valid value, or, if an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

OPTIONSのヘッダーのAccess-Control-Allow-Originの値と実際のメソッドのヘッダーで返しているAccess-Control-Allow-Originの値が異なる。

SSL 証明書を結合する

以下はやった時のメモになります。その時は以下のファイルがありました。

  • csr(Certificate Signing Request) コモンネームや組織名が含まれているファイル
    • -----BEGIN CERTIFICATE REQUEST-----が含まれる
  • cer, ca, crt デジタル証明書ファイル
    • -----BEGIN CERTIFICATE-----が含まれる
    • ルート証明書と中間CA証明書?(恐らくcerca
    • サーバー証明書?(恐らくcrt
    • 全部certificateの略?
  • rsa 秘密鍵ファイル
    • -----BEGIN PRIVATE KEY-----が含まれる

ファイルの確認

手元に有るファイルが上記以外の拡張子だった場合、以下の方法で確認することができます。

// Certificate Signing Request か?
openssl req -text -noout -in <filename>

// cer(crt?) か?
openssl x509 -text -noout -in <filename>

// rsa か?
openssl rsa -text -noout -in <filename>

結果が長々と出てきたり(Bash)echo $?や(Fish)echo $status0だったものが正です。

今回はcer(crt?)ファイルがすでに複数存在していたので、 証明書発行の為の Certificate Signing Request は扱わなくて良いようです。

結合

また複数存在しているcer(crt?)ファイルを 1 つのファイルに結合する必要がありますが、上記のopenssl x509を実行した時にSubject:の値がCN=自分のドメインとなっているファイルをが先頭に来るようにします。(複数ある場合は、Issuer:も見て次にその証明書が来るように結合しないと駄目?)

以下のような形で結合します。ただcatで結合すると-----END CERTIFICATE----------BEGIN CERTIFICATE-----のようになってしまうので、<(echo)によって改行を挟んでいます。

また、権限は400に設定します。

cat www.example.com.cer <(echo) ca.cer > result.crt
chmod 400 result.crt
# できたファイルに対しても確認をしておく
openssl x509 -text -noout -in result.crt

できたらサーバーに上げて更新します。

参照

Basic Auth

Basic Auth(Basic 認証)を使うと Web ページに簡単な認証を付けれます。認証はユーザー名とパスワードのペアから成るもので、このペアが一致した場合のみ本来のリクエストを取得できます。
セキュリティとしては貧弱ですが、ちょっとした Web サイトの開発中などに特定の誰かとのネットを介した共有などを行うにあたっては割と便利です。

仕組み

を作りました。

PlantUML では。

@startuml
participant browser
participant server

autonumber

browser -> server: アクセス

loop
  alt 認証が失敗
    server -> browser: 401\nwww-authenticate: Basic realm=... を返す
    browser -> browser: 認証ダイアログを出す
    opt ユーザー名とパスワード入力
       browser -> server: authorization: Basic ... を送信
       server -> server: 認証
    end
  else
    server -> browser: 200
  end
end


@enduml

認証が失敗した時

www-authenticate: Basic realm="..."ヘッダーを持たせて401ステータスコードでレスポンスを返します。(...は適当な文字列になります)
このヘッダーを持つ401レスポンスを受け取ったブラウザは自動的に認証ダイアログを表示してくれます。

ダイアログにはキャンセルボタンもあるので、ユーザーがそれをクリックした場合、そこで一連のフローは終わります。

ユーザーがユーザーとパスワードを送信した場合、サーバーではauthorization: Basic ...というヘッダーが含まれて送られてきます。(...はユーザー名とパスワードを:で繋げてbase64化したものです サーバーはそのヘッダーからbase64化された部分を取り出し、自分たちの持つ認証情報とマッチするか確認します。

ここで認証が失敗すればまた401www-authenticate付きで送り上記のフローを繰り返し、認証が成功すれば200で本来受け取るべきレスポンスを受け取ります。

リポジトリ

ExpressJS で作ったです。以下で起動して、

yarn && yarn dev

localhost:9997/foolocalhost:9997/barといった URL で確認できます。

iframe 制限: x-frame-options header

ヘッダーにx-frame-optionsを含めると、そのレスポンス結果をリファラーサイトの<iframe>で表示しても良いかどうか決めれます。

このオプションは次の2つ(3つ)の値を持てます。

  • deny
  • sameorigin
  • allow-from <url>

ただし3つ目のallow-from <url>は古いのかうまく設定が効きかなかったので、覚えなくて良いかもしれません。

deny

リファラサイトへの<iframe>での埋め込みを禁じます。禁じられた場合 Chrome では接続拒否画面が表示されます。

allow-fromが使えないので、もしサイトによって許可・不許可の制御が必要なのであればrefererヘッダーを都度見てx-frame-options: denyを設定する必要がありそうです。

sameorigin

同ドメイン内だけに<iframe>埋め込みを許可したい場合はこの値です。例えばlocalhost:3000/contentsを埋め込む場合、localhost:3000では大丈夫ですが、localhost:30001では接続が拒否されます。