概要

このプログラムは、「利用者ごとにFrogNoteのバックアップデータを永続化する」ためのAPIサーバです。 実際に運営するサービスではないため、全ソースを公開しています。 サーバ開発の勉強用のため、エラーハンドリングなどは雑におこなっています。

設計と実装

設計 このような単純な階層化アーキテクチャを採用しています。

Application層を置いていない理由

現状、サーバ側ではユースケースを定義していないからです。ユースケースはクライアント側で設定できるようにした方が、利用しやすいAPIになると思ったからです。 そのため、サーバ側では基本的なCRUD操作や、認証の仕組みだけを提供しています。

HandlerをUI層を置いていない理由

現状、UIにあたる処理がHandlerだけかつ、GUIと違ってUIに関する複雑な処理はないため、Infrastructure層内部に実装しています。

Entry層

Entry層ではアプリケーションの起動処理(一度だけ行う処理)を行います。 そのため、非常に薄いレイヤとなっています。 具体的には、Server構造体の変数にハンドラを設定して起動しています。

Infrastructure層

この層が実際の処理を担当する層となっています。 大きく三つのモジュール群に分けられます。

  1. servers
  2. security
  3. db

servers

このモジュールには、サーバ本体、ハンドラ、ロガーが含まれ、HTTPリクエストを受信するのが目的となっています。

security

このモジュールは、パスワードのハッシュ化、アクセストークンの管理など、セキュリティインフラを担っています。

db

このモジュールはMySQLにアクセスし、ドメインモデルを永続化・復元します。

Domain層

現状この層はドメインモデルを表現するための層になっています。「利用者ごとにFrogNoteのバックアップデータを永続化する」という目的なので、今回の場合、「ユーザ」、「バックアップ」がドメインモデルにあたります。

セキュリティと懸念事項

SQLインジェクション攻撃の対策

SQL文の組み立ては単純な文字列置換を行わず、プレースホルダを用いています。

HTTPSではない

現状HTTPでサーブしています。GitHubに公開することを考えると証明書までプッシュしないといけなくなるからです。 HTTP通信では通信が暗号化されていなかったり、証明が行えない問題はありますが、今回は扱わないものとしています。

パスワード管理

パスワードは必要最低限の処理をしてからデータベースに格納しています。 具体的には、SHA-256で10,000回ハッシュ化してから格納しています。もし、これ以上の対策を行うとすれば、ハッシュ化時にSaltやPaperを用いるとさらに堅牢になります。

セッション管理

セッション用のIDをサインイン時に発行し、通信しています。セッションIDはuuidを用いているので推測が困難です。 また、セッションIDは、サーバ内部の辞書(map)でユーザIDと紐づけて管理しています。

セッションの破棄タイミング

クライアント側がサインアウトしたことを通知した際に破棄するようにしています。実際に運用する場合は、時間経過で破棄することも必要になると思います。

認証方法

AuthorizationヘッダのセッションIDが存在するかで認証済みか認証されていないかを判定しています。 そのため、セッションIDが盗まれると乗っ取りが可能な仕組みです。

サインイン時の認証

サインインする際は、ユーザからサインインID、パスワードが送信されます。 パスワードは平文が送られるので、一度ハッシュ化してからデータベース内のパスワードと比較しています。 リプレイ攻撃の対策はしていないので、チャレンジ&レスポンス認証に切り替えることを検討する必要があります。