knokcs アカウント登録なしの共有サービスを開発した話
端末間で文字や写真をやり取りしたいだけなのに、メールやLINEアカウントなどのアカウントを交換するのが面倒だったので、アカウント登録なしで使えるサービスを作りました。
サービス名はknocks です。
この記事では、サービスの概要とハマりポイントをまとめます。
背景
やりたかったことはシンプルで、
- アカウント登録・ログイン不要
- URLなどの文字や写真を共有したい
- 簡単な仕組みにしたい
自分で使いたいので、SEOされなくても手入力できる短いドメイン(k-nox.jp)は必須でした。
サービス概要
やることは単純です。
-
k-nox.jpにアクセスすると、新しい「スペース」(1.k-nox.jpのようなURL)が発行される - スペースのQRコード、あるいは番号を他の端末に伝える
- 相手はそのスペースにアクセスして参加リクエストを送り、メンバーが承認するとテキスト・ファイルのやり取りができる
- 一定時間でスペースは削除される
ログイン画面はなく、アカウントという概念もないので、パスワードを忘れることもありません。
技術構成
サーバーサイドはCloudflare Workers、状態管理はDurable Objectsを使っています。
| 領域 | サービス | 採用理由 |
|---|---|---|
| 実行環境 | Cloudflare Workers | 静的アセット配信・API・WebSocketを1つのWorkerにまとめられる |
| 状態管理 | Durable Objects | スペースごとの状態が1インスタンスで完結する |
| ファイル保存 | R2 | Workerからバインディングで直接読み書きでき、ダウンロード通信無料 |
DBを導入しなかったのは、Durable ObjectがSQLiteを内蔵しており、普通にSQLが書けることです。
スペース単位で閉じたデータしか扱わないので、これで十分でした。
採番の工夫:単調増加カウンター+空き番号プール
スペース番号はできるだけ短くしたいので、1, 2, 3...と単調増加で払い出しています。
スペースが空室になると、空いた番号を再利用する仕組みを入れています。
Durable Objectsには、ストレージ操作が完了するまで同一インスタンスへの次のリクエストを待たせる仕組みがあるので、「最大値を読む→+1する→書く」という処理を1つのDurable Object内で完結させれば、明示的なロックを書かなくても二重採番は起きません。地味に便利でした。
リアルタイム同期:WebSocket Hibernation API
同じスペースを共有している端末間でリアルタイムに反映するために、WebSocketで状態を配信しています。Durable ObjectsのWebSocket Hibernation APIを使うと、接続がアイドル状態の間はDurable Object自体をスリープさせられるので、常時接続を維持するわりにコストを抑えられるのがありがたいです。
ハマりポイント
空きスペースの再利用で、情報漏洩
空室になったスペース番号を再利用する仕組みを入れたところ、「前にそのスペースにいた端末が、新しいスペースにアクセスできる」という問題が発生しました。
対策として、スペースに世代IDを持たせ、一致しない場合は無効化するようにしました。番号は同じでも「別のスペース」として扱う、という考え方です。
セキュリティ
アカウント必要なし、短いURLなど、攻撃してくれと言わんばかりのサービスです![]()
自分しか使わない前提でサービスを構築していましたが、公開するにはどこまでやればいいのか調べているうちに面白くなってしまいました。
一番のハマりは空きスペースの再利用でした。
制約ありますが、普通に使うには問題ないはずです。
まとめ
アカウント登録なしで完結するサービスを、Cloudflare Workers + Durable Objectsで作った話でした。
個人利用が前提のサービスですが、Durable Objectsの入出力ゲートやWebSocket Hibernationは、実際に使ってみると良さが分かりました。
サービス自体はこちらです。よかったら覗いてみてください。