どうも、小野です。
アプリケーションによって、要件に合わせたセッション管理は様々ですので、管理方法に正解はありません。 セキュリティは担保できるのか、実装工数はどのくらいなのか?など、要件に応じてベストな選択ができるようある程度の選択肢を持っておく必要があります。
セッション管理はアプリケーションにとって、切り離せない存在なので、毎回どういう方式にするか頭を悩まされます。
今回お話することは、私が今まで開発に携わってきた経験から得た知見です。 参考にしていただけたら幸いです。
サーバによる管理方法
サーバではセッションID、トークンの発行、検証を行います。
サーバによる管理方法には3つあります。
- サーバのメモリで管理
- DBで管理(インメモリDB、RDBなど)
- JWT(Json Web Token)※
※実際はトークン自体、サーバで管理しませんが、トークンの発行、検証を行うため、サーバ側の管理としています。
サーバのメモリで管理
アプリケーションサーバ内のメモリにセッション情報を保持する方式です。 サーバのクラウド化が進み、スケーラビリティが重要視されてきているので、 この方式はあまりお勧めできません。
メリット
- どの言語のフレームワークでも、組み込まれているため実装が容易である。
デメリット
- サーバ再起動によりセッション情報がクリアされる。(ログイン中のユーザは強制ログアウト)
- 負荷分散する際、スティッキーセッション※を利用する必要があるため、十分な負荷分散が期待できない。
※スティッキーセッションとは、セッションIDが発行されたサーバにセッションが切れるまでアクセス先を維持する機能です。
DBによる管理
メリット
- アプリケーションサーバに依存しないので、再起動してもセッションは維持される。
- サーバによるメモリ管理のデメリットは解消される。
デメリット
- 別サーバを立てるためコストや保守が必要になる。
JWT
メリット
- サーバ側をステートレスにできる。
デメリット
- サーバでセッションを管理していないので、盗まれた時の対処ができない。
- セキュリティを担保するための実装が複雑になる。
セキュリティ対策
対策としては2つあります。
- JWTの有効期限を短くし、期限切れの場合にJWT更新用のトークン(リフレッシュトークン)を利用して更新する。
- リクエスト毎にJWTを生成する。
上記のシーケンス図で分かる通り、サーバで制御できない分、実装は複雑になります。
評価
以上の見解から、以下のような評価になりました。
比較項目 | サーバ | DB | JWT |
---|---|---|---|
実装容易性 | 〇 | 〇 | △ |
コスト | 〇 | △ | 〇 |
スケーラビリティ | △ | 〇 | 〇 |
セキュリティ | 〇 | 〇 | 〇(条件付き) |
クライアントのよる管理方法
クライアントでは、セッションID、トークンの保持、送信を行います。基本的に検証は行いません。
クライアントによる管理方法には2つあります。
- Cookie
- LocalStrage
他に、SessionStrageもありますが、タブごとの管理になってしまうためあまり実用的ではないので除外しました。
Cookie
メリット
- リクエスト、レスポンス時にクライアント側で意識する必要ない。
- HttpOnly属性設定することで、Javascriptからはアクセスできない。
- Secure属性を設定することで、HTTPSのみ送信される。
デメリット
- CSRF(クロスサイトリクエストフォージェリ)脆弱性があるため、何らかの対策が必要になる。 CSRFについては、こちらを参考にしてください。
CSRF対策
一般的な方法をご紹介します。
LocalStrage
メリット
- CSRF対策を考えなくてよい。
デメリット
- リクエスト送信時にLocalStrageから取得して付与や、レスポンス受信時にLocalStrageへの保存を自前で行う必要がある。
- Javascriptからアクセスできるため、XSS(クロスサイトスクリプティング)脆弱性がある。※
※アプリケーションを構築する上でXSS対策は必須なので、無視しても問題ないと思います。
XSSについては、こちらを参考にしてください。
XSS対策
scriptタグで使う「<>」をエスケープすることで対応できます。
例)「<>」 →エスケープ→&lt;&gt;
(&は本来は小文字です。エスケープと認識されてしまうため大文字で記載しています)
評価
以上の見解から、以下のような評価になります。
比較項目 | Cookie | LocalStrage |
---|---|---|
実装容易性 | 〇 | △ |
セキュリティ | 〇(CSRF要対策) | 〇(XSS要対策) |
CSRF対策が可能であればCookie、難しいのであればLocalStrageを使うのが良いかと思います。
おわりに
サーバ、クライアントによるセッション管理方法を紹介しました。組み合わせパターンは様々ですが、要件に応じて選択することが重要です。 ただ、その中でもおすすめな組み合わせを知りたいという方もいると思うので、個人的な意見としてご紹介します。
サーバ | クライアント |
---|---|
DB | LocalStrage |
DBを選択した理由
DBは、インメモリDB(KVS)を利用します。具体的な製品を挙げると、「Redis」や「Memcached」などです。 スケーラビリティにも対応できて、実装も容易であることから選びました。
LocalStrageを選択した理由
Cookieの場合、CSRF対策は必要になりますので、クライアント側の実装は多少手間になっても、 CSRF対策に比べたら容易であることから選びました。