はじめに
ここでは具体的な実装やアーキテクチャの話ではなく、webサーバーの認証機能についてざっくりと理解するための情報をまとめています。
どの認証方法を選べばいいのか、へのヒントになれば幸いです。
Webサーバーの認証機能
クライアントがWebサーバーにアクセスする際に、サーバー側がクライアントを特定・認可するための機能です。
セキュリティの観点から、認証機能はWebサーバーには欠かせない存在とも言えます。
この認証方法には大きく分けて3種類。
HTTPがサポートするBasic認証・Digest認証、設計者が自分でログイン用htmlページを用意するForm認証です。
Basic認証
Webサーバーへのアクセスで使われるHTTPプロトコルでサポートされているユーザー認証方式の1つです。
クライアントがWebサーバーにアクセスすると、ログイン用のダイアログがブラウザに表示され、ダイアログにあらかじめ登録していたUsernameとPasswordを利用者が入力する仕組みです。
入力したUsernameとPasswordをBase64はエンコードされて、サーバーに送信されます。
特にハッシュ化も暗号化もしていないので、盗聴・デコードされてしまえば中身は丸見え。
これがBasic認証の大きな特徴であり、大きな問題です。
しかし、この問題はSSL/TLSプロトコル (ここではhttps)で通信をすれば暗号化されるので解消されます。
この記事ではSSL/TLSの暗号化については割愛します。
Basic認証は比較的実装が容易で、ほとんどのWebサーバー及びブラウザで対応しています。
よく聞くApacheやNginxのようなWebサーバーソフトウェアを用いて、設定することができます。
Basic認証ではログアウト機能はありません。
というのも、Basic認証ではブラウザが認証状態を握っているため、認証状態はブラウザを終了するまで残ります。
簡易的であればログアウト機能っぽいものも作れそうです。
本格的にログインログアウト機能やアカウントによるアクセス権限を付けたければ、Form認証が必要となります。
Digest認証
Digest認証もBasic認証同様にHTTPプロトコルでサポートされているユーザー認証方式の1つです。
唯一の違いは、UsernameとPasswordをハッシュ化してサーバーに送信することです。
主にSSL/TLSでの通信ができない環境で使われる方式だと考えられます。
クライアントがサーバーにアクセスした際に、サーバーはクライアントにログイン画面と共にnonceとMD5のようなハッシュ化に使う関数を送ります。
クライアントは、ハッシュ化パスワード = MD5(nonce+Password)をサーバー側に送り返し、サーバー側にもともと登録してあるハッシュ化パスワードと比較することでユーザー認証が可能になります。
ここで、ハッシュ化パスワードごと盗聴し、そのデータをそのまま用いてログインするリプレイ攻撃への対策としてnonceが登場します。
nonce(number used once)とは使い捨てのランダム値であり、これに有効期限を定めることによって上記の攻撃を防ぐことができます。
ハッシュ化とはMD5やSHAなどのハッシュ関数を用いて、いかなる長さのデータであっても固定長の擬似乱数データに置き換えることを意味します。
ハッシュ化では同じ入力値に対して、必ず同じ出力になります。
異なる入力値に対しては、必ず異なる出力とは限りませんが、それがこのハッシュ関数の精度にかかっています。
暗号化との違いは、復元できるかどうか、です。
その値を元に戻す必要があるかどうかで暗号化との使い分けされます。
例えば、1つのユースケースとしてサーバー側にあらかじめパスワードを登録してログインする際に、サーバー側はハッシュ化されたパスワードさえ知っていれば、送られてくるハッシュ化後のパスワードと比較して認証することができます。
つまり復元する必要がないので、暗号化ではなくハッシュ化を利用します。
もとより、セキュリティの観点から生のパスワードや復元可能な状態のパスワードをサーバー側に保存すること自体がNGです。
Form認証
Form認証とは自分で実装したhtmlのログインフォーム画面からUsenamseとPasswordを送信する認証方式です。
平文でのやりとりのため、SSL/TLSでの暗号化通信上で使われるのが一般的です。
一から自分で作るため、実装の難易度は上がりますが、その分自由度が高くなります。
上の2つと異なり、セッションという概念が登場し、ログイン状態がサーバー側で管理されます。
このセッションが有効な期間のみ、サーバーへのアクセスが可能になります。
そのため、Basic・Digest認証ではできないログイン/ログアウトという機能が使えるようになります。
具体的には、認証不要なログインページにUsernameとPasswordを入力・送信してサーバー側に登録されている情報と比較することで認証します。
認証情報を保存するために、セッションIDを発行し、レスポンスクッキーにセッションIDを付与します。
その後のページアクセスにはセッションIDの情報を含めてアクセスされ、サーバー側でセッションIDとセッションデータを照合し、アクセス許可を出します。
このよう実装の自由度も高いため、アカウントによって機能やページを制限することが可能になります。
管理者しか入れないページと一般アカウントも入れるページを区別したい時にはこのForm認証が必要になります。
最後にまとめたい
のですが、メモなので特にまとめはないです。
追加の重要な情報やご指摘あればください。
ハッシュ化や暗号化方法については奥が深そうなので時間があればまた別に書きたいところです。