ログインの基礎まとめた
目的
ログイン機能を理解するために、最初のステップとしてログインの基礎を学習する。
ログイン機能の仕組み
一般的に、ログインする際にユーザーを識別するための情報は
・メールアドレス(or ユーザー名など)
・パスワード
この組み合わせを使用し、データベースに登録されているリストからログインするユーザーを検索する。
ユーザーが見つかった場合、プログラムはそのユーザーの情報をセッションに保存し、それ以降の画面では「セッションにログイン情報があるかどうか」をチェックする。
引用:https://blog.senseshare.jp/login-mechanism.html
しかしセッションは、未操作状態で一定時間経つと自動的に破棄されるため、ログイン状態をずっと保持させておくことは出来ない。
そこで、次回以降自動的にログインさせる仕組みとして、ユーザーが操作するブラウザのCookieというデータの保存領域を活用する。
最初にログインした際、トークンを発行し、それをCookieとデータベースに保存する(トークンにはセキュリティのために有効期限も設定しておく)。
引用:https://blog.senseshare.jp/login-mechanism.html
次にユーザーがアクセスした時
- Cookieにトークンがあるかどうかをチェック。
- あればそのトークンをデータベースと照合。
- トークンが一致するユーザーデータが存在し、有効期間内であれば、そのユーザーで自動ログインさせる。
(ユーザーによってログアウトが行われた際は、トークン情報も削除する。)
引用:https://blog.senseshare.jp/login-mechanism.html
Laravelの認証・認可
Laravelにはログインを実現するためのパッケージが備わっており、Laravelの認証機能は素早く、安全な方法で実装が可能である。
認証と認可の違い
認証(Authentication):そのユーザが誰であるかを判断すること
認可(Authorization):そのユーザで何ができるかを判断すること
引用:https://qiita.com/mgmgmogumi/items/722567cd2f1421d7e11c
認証の仕組み
認証はミドルウェア(OSとアプリケーションの間に入って処理を行うもの)を使って実現しており、リクエスト・レスポンス時にフィルタリングを行ってくれる。
ログインの認証では、web・guest・authの3つのミドルウェアを使用している。
認証前
認証後
ミドルウェアの定義
app/Http/Kernel.php
でミドルウェアの定義をしている。
$middleware → 全ての処理に共通して処理を行うミドルウェアを定義。各ルートが呼ばれたときに実行される。
$middlewareGroups → 複数のミドルウェアをグループとして定義。
$routeMiddleware → 単体で使うミドルウェアをキーと共に定義。
認証・認可のカスタマイズ
Laravelでは、デフォルトでconfig/auth.phpに認証の設定がされている。
独自の認証のカスタマイズをしたい場合は、GuardやProvierを設定し、認可のカスタマイズをしたい場合は、GateやPolicyを設定する。
Guardは各リクエストのユーザー認証を定義し、Provierは永続ストレージ(MySQLなど)からのユーザーの取得方法を定義する。
認証パラメータはconfig/auth.php
ファイルで定義し、認証の振る舞いを調整するオプションを設定することができる。
(カスタムGuardはAuthServiceProvider.php
で定義する。)
ミドルウェアの使用
ミドルウェアの使用方法には主に二つのやり方がある。
- ルーターでミドルウェアを使用する。
- コントローラーでミドルウェアを使用する。
(webのミドルウェアはroutes/web.php
のルートに対して使用されている。)
使用例:routes/app.php
でカスタムGuardを使用など
Basic認証・Bearer認証
HTTP上で認証を行う場合
- セッションによる認証
- リクエストボディにトークンを含める認証
- 独自ヘッダにトークンを含める認証
- Authorizationヘッダーを用いた認証(Basic・Digest・Bearer・OAuth)
- JWT認証など
様々な方法がある。
Basic認証
ほぼすべてのWebサーバー・ブラウザ・ツールで実装されているため、簡単に導入することができる。
セキュリティ面にデメリットがあり、簡単にユーザ名、パスワードを盗まれてしまう
(採用されているBase64は暗号化ではないため)。
Basic認証方式を採用する場合、HTTPSを利用することが必須条件となる。
本来はWebサーバー内のディレクトリへのアクセスを管理するため技術のため、Single Sign Onのようなサービスを跨いだ認証はできない。
(↑ example1.とexample2.のように同時認証ができない。)
動作の流れ
- ブラウザがRequestを送る
- サーバーがBasic認証が必要なことを伝える(WWW-Authenticateヘッダに「Basic」をセットした401 Authorization Requiredを返信)
- ユーザーがユーザー名とパスワードをブラウザに入力する
- ブラウザはユーザー名とパスワードを「:」でつなげてBase64でエンコードしてAuthorizationヘッダーにセットしてRequestを送る
- サーバーはユーザー名とパスワードをBase64でデコードして認証を行う
- 認証が成功すると、サーバーはRequestされたページを送る
- ブラウザは認証状態をキャシュし、キャッシュがクリアされるまでユーザーが再認証を要求されることはない
動作5で認証に失敗した場合は、401(Unauthorized)、認可に失敗した場合は403(Forbidden)が手順6で送られる。
(ブラウザが前提になっているが、Web APIの場合は事前に認証が必要なことを知っているので動作1〜3がなくなる)
Bearer認証
Bearer認証は, トークンを利用した認証・認可に使用されることを想定しており、HTTPでも使用しても良いとされている。
HTTPのAuthorizationヘッダにスキームとして指定でき、「 Authorization: Bearer <token>
」のように指定する。
トークンの形式はtoken68の形式で指定することが定められている
(1文字以上の半角英数字, - (ハイフン), . (ドット), _ (アンダーバー), ~ (チルダ), + (プラス), / (スラッシュ)から構成された文字列)
動作の流れ
- クライアントは、事前に入手したアクセストークンをtoken68形式でAuthorizationヘッダーにセットしてRequestを送る
- サーバーはアクセストークンが有効なものか確認する
- アクセストークンが有効だった場合、Webサーバはークライアントが要求したリソースを送る
動作2で認証が失敗した場合、サーバーは401(Unauthorized)を返信する(WWW-Authenticateヘッダ内のerrorパラメータに失敗した原因が記載されている)
・成功
WWW-Authenticate: Bearer realm=""
・リクエストにAuthorizationヘッダが含まれていない(401 Unauthorized)
WWW-Authenticate: Bearer realm="token_required"
・トークンが失効, 破損しているケース(401 Unauthorized)
WWW-Authenticate: Bearer error="invalid_token"
・トークンのスコープが不十分なケース(403 Forbidden)
WWW-Authenticate: Bearer error="insufficient_scope"
機密性の高いデータを扱うサービスでは、比較的安全なBearer認証、OAuth認証方式を目にすることが多い。
参考ページ:
ログインってどういう仕組み?:https://blog.senseshare.jp/login-mechanism.html
Laravelの認証機能を徹底解説:https://kinsta.com/jp/blog/laravel-authentication/
Laravelの認証の仕組み:https://qiita.com/mgmgmogumi/items/722567cd2f1421d7e11c
Laravel の Guard(認証) って実際何をやっているのじゃ?:https://qiita.com/tomoeine/items/40a966bf3801633cf90f
Bearer認証について:https://qiita.com/h_tyokinuhata/items/ab8e0337085997be04b1#bearer認証
Basic認証、Digest認証、Bearer認証、OAuth認証方式について:https://architecting.hateblo.jp/entry/2020/03/27/130535
Discussion