WEBのデータ通信入門まとめ(GET/POSTメソッド、Cookie、セッションID)

# はじめに
- 自己紹介：UbuntuでPythonを書いてデータ分析とか異常検知してます。
- [Twitter](https://twitter.com/norihitoishida)やってます。
- WEBを勉強していてGET/POSTメソッド、Cookie、セッションIDあたりで躓いたのでまとめました。
- 間違いや加筆すべきことがあったら教えて下さい。

# 目次
- WEBクライアントとWEBサーバの通信の流れ
- GETメソッドとPOSTメソッドの比較
- CookieとセッションIDの比較

# WEBクライアントとWEBサーバの通信の流れ
WEBクライアント(ブラウザ)とWEBサーバ(アプリ)の通信は以下のような流れで行われます。
①人間：ブラウザにURLを入力する
②ブラウザ：URLに従ってWEBサーバにHTTPリクエストを送る(例：「hoge.htmlを下さい」と伝える)
③サーバ：HTTPリクエストに従ってHTTPレスポンスを返す(例：hoge.htmlファイルを渡す)
④ブラウザ：HTTPレスポンスに従ってHTMLファイルを読み、表示する

>補足
URL(文字列)をIPアドレスに変換する必要があるため、本当は①と②の間にDNSサーバと通信しています。
今回の話とはあまり関係ないので割愛しています。

HTTPリクエストやHTTPレスポンスは、Chrome Developer Toolsで確認する事ができます。
![http_rsp.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/331449/211b627a-44f0-2dc0-534f-510d11ba5ce3.jpeg)
F12キーでChrome Developer Toolsを開き、https://www.google.com/ にアクセスします。
「Network」を選択→Name列の「www.google.com」を選択→「Header」を選択します。
これでgoogleにアクセスした際のHTTPリクエストとHTTPレスポンスを見ることができます。
**Request Method: GET**とあることから、GETメソッドでHTTPリクエストを送った事がわかります。
メソッドは8種類あり、[こちら](https://qiita.com/r_fukuma/items/a9e8d18467fe3e04068e)のQiita記事がわかりやすいです。
今回は、よく使うGETメソッドとPOSTメソッドを比較しようと思います。


# GETメソッドとPOSTメソッドの比較
Chrome Developer Toolsを開いたままgoogleで「Qiita」と検索→Name列の「search?(以下略)」を選択→「Header」を選択します。
長くて探すのが大変ですが、Request URL:欄に**?q=Qiita**という文字列があります。
このように、値(Qiitaという文字列)を特殊文字**?**を挟んでURLにくっつけることでWEBサーバに渡すのがGETメソッドです。
くっつけた文字列のことを「クエリストリング」と呼びます。

URLに値がくっついているので、結果を保存したり配布したりするのに楽です。
https://www.google.com/search?q=Qiita をブックマークすることで、いつでも「Qiita」と検索した際の結果を確認できます。
URLを他人に送ることで、値ごと人に伝える事もできます。

一方、パスワードなどをGETメソッドで送ってしまうと、サーバのログに残ったリクエストラインから情報が漏洩する危険があります。
そこでPOSTメソッドというリクエストボディ内に値を記入する手法を使うことによって、情報漏洩のリスクを下げる事ができます。

まとめます。

**GETメソッド**
①人間：ブラウザに情報を入力する
②ブラウザ：URLに情報をくっつけて、サーバに送る
メリット：値を保存・再現しやすい
デメリット：セキュリティが低い
向いているもの：検索など

**POSTメソッド**
①人間：ブラウザに情報を入力する
②ブラウザ：リクエストボディ内に情報を記入し、サーバに送る
メリット：セキュリティが高い
デメリット：値を保存・再現しにくい
向いているもの：パスワードやIDなど

>補足
用語が入り乱れると話がわかりにくくなるので「URLに情報をくっつけて」と書きましたが、
「リクエストライン(メソッド+URI+HTTPバージョン)に付加して」といった方が正確です。

GETメソッドとPOSTメソッドのさらなる詳細を知りたい方は[こちら](https://qiita.com/7968/items/4bf4d6f28284146c288f)のQiita記事がわかりやすいです。

続いて、WEBアプリケーションにIDとパスワードを送ってログインした後、
どうやってログイン状態を保つのかという問題を考えたいと思います。

HTTPはステートレスなプロトコルです。
つまり、HTTPを使ってやり取りしたサーバとブラウザは情報を保持できません。
>補足
ステートフル(情報を保持できる)なプロトコルの一例としてFTPがあります。
FTPはコネクションの確立や認証などオーバーヘッド(本来の目的ではない通信)が大きく、実装も大変です。
より手軽なプロトコルを作ることを目的にHTTPが開発された、という経緯があります。

そこでCookieとセッションIDという考え方が登場します。

# CookieとセッションIDの比較
サーバからブラウザへ送られる**レスポンスヘッダ**の中に、Set-Cookieというヘッダがあります。
ブラウザはSet-Cookieヘッダで指定された値を保存しておき、2回目以降のリクエストヘッダにCookieヘッダとしてその値を付加します。
サーバはその値を読んでブラウザを特定する、という仕組みです。
ログアウトする際は、Set-Cookieヘッダを無で上書きする事でCookie情報を消去します。

これによってサーバとブラウザは情報を保持できるようになりましたが、以下のようなデメリットもあります。

- 保存されたCookieを盗み見られる(PC上にテキストファイルとして保存されます)
- 通信を傍受されリクエストヘッダやレスポンスヘッダに書いたCookieが盗み見られる

そこで考えられたのがセッションIDです。
サーバは、クライアントごとの情報(ID、パスワードなど)をセッションという表に保存し、一意なセッションIDを割当てます。
それをCookieヘッダでやり取りする事によって、セッションIDが漏洩しても情報(ID、パスワード、閲覧履歴など)は漏洩しない、という仕組みです。

- ブラウザは生データを保存しないので安心
- 2回目以降の通信には生データが載ってないので傍受されても安心

という事です。

まとめます。

**Cookie**
①人間：ブラウザに生データ(ID、パスワードなど)を入力する
②ブラウザ：リクエストヘッダ内に生データを記入し、サーバに送る
③サーバ：レスポンスヘッダ内のSet-Cookieヘッダに生データを記入し、ブラウザに送り返す
④ブラウザ：2回目以降、リクエストヘッダ内のCookieヘッダに生データを記入し、サーバに送る
⑤サーバ：Cookieヘッダに書かれた生データを読んで、サーバがブラウザを特定する

**セッションID**
①人間：ブラウザに生データ(ID、パスワードなど)を入力する
②ブラウザ：リクエストヘッダ内に生データ(ID、パスワードなど)を記入し、サーバに送る
③サーバ：サーバ内に生データ(ID、パスワードなど)をセッションとして保存する
　　　　　セッションに対応するIDを発行する
　　　　　レスポンスヘッダ内のSet-CookieヘッダにセッションIDを記入し、ブラウザに送り返す
④ブラウザ：2回目以降のリクエスト時、リクエストヘッダ内のCookieヘッダにセッションIDを記入し、サーバに送る
⑤サーバ：Cookieヘッダに書かれたセッションIDを読んで、サーバがブラウザを特定する