モチベーション
先日JWTに入門した*1が、そもそも認証認可について何も分かっていないので、度々目にするセッション管理について実装した。
セッション管理 とは
- HTTPはステートレスのため、Webサーバーに対する複数リクエストが同一クライアントから送信されたか判別できない
- 電子商取引サイトのようにWebサーバーにユーザーがログインしてからログインするまで、ログイン情報を保持する必要がある場合は素のHTTP通信で実現できない
という背景がある上で、
- クライアントとサーバー間でログイン情報を保持し、アクセス制御を一つの集合体として管理する仕組みが必要となる。この仕組みをセッション管理と呼ぶ
- セッション管理を実現する一般的な方法に、Webサーバーが発行するセッションIDを利用するものがある。これは、クライアントがWebサーバーにログインした際、セッションIDを発行し、以後、その情報を基にクライアントとWebサーバーのセッション管理を行う
(なかなかちゃんとしたところが出している情報源が無くて、たどり着くまでに時間がかかった。)
上記を頭に入れてGoで実装してみた。
リポジトリ
処理の流れ
- ユーザーがログインページにアクセス
- ユーザーがIDとパスワードを入力
- ブラウザがサーバーにIDとパスワードをPOST
- サーバーはIDとパスワードが合っているか確認
- サーバーがセッションIDを生成(今回はUUIDを利用)
- サーバーはCookieにセッションIDを設定してブラウザに返す
- 6以降のブラウザからサーバーへの通信でセッションIDが含まれたCookieが送信される
- サーバー側でCookieに含まれたセッションIDを確認してユーザーを識別
所感
- セッション管理を用いた認証(= セッション認証)は認証の文脈で入門という理解だったが、考えることがとても多いと感じた(入門だからといって簡単な訳ではないよ、ということか)
- セッションIDの寿命(固定値? ユーザーのログアウトで失効?)
- セッションIDの管理(DB? メモリキャッシュ?)
- セッションIDの漏洩防止
- CookieにセッションIDをもたせるだけで良いのか?セッションIDを知られたらなりすましが容易なので認証に他の要素が必要なのでは?
- Goだけかもしれないが、サーバー側の実行時エラーをブラウザ側にどう伝えるか悩ましかった
- 全部500(InternalServerError)に丸める?
- サーバー側の責務の範囲が悩ましかった。下記3つの責務を今は一つのDockerコンテナが担当しているが、それぞれ別コンテナが良いのか悩ましい
- フロントエンド(今回でいうHTMLファイル)を提供する責務
- セッションを管理する責務
- セッションIDを発行する責務