本記事は、以下の記事の続きです。

前回の復習と今回の内容
運用型ライブゲームを作るためには、クライアントとサーバ側で適宜通信を行う必要があり、通信を行うためには、クライアントからリクエストを投げて、サーバからレスポンスを受け取る、という流れが必要でした。
どのエンドポイントにどんな形式のリクエストで送るのか、そのリクエストのどういうレスポンスが返ってくるかを定義しているのがAPIであり、クライアントからAPIを呼び出すことで必要な通信が行える、というのが前回解説した内容でした。
今回の記事では、実際の運用に耐えるためには、クライアントからサーバに通信を行う際に、どのようなことをセキュリティ的な対策を講じる必要があるかについて解説していきます。
HTTP(s)とはなにか?
前回の記事では、このAPIとして定義する内容の中に、「エンドポイント」というものがありました。
これは、サーバにアクセスするためのURLのことです。
URLは、みなさんおなじみの以下のような形式をしています。
この頭についている、http
であったり、https
とはなにか、疑問に思ったことはないでしょうか?
HTTPとはなにか?
HTTP(HyperText Transfer Protocol)は、インターネット上でクライアントとサーバでデータをやり取りするための「共通言語」です。
前回の記事で解説した、リクエスト、レスポンスといったものは、このHTTPのプロトコルの一員です。

HTTPは以下のような特徴があります:
- 平文通信:送信内容がそのまま見える状態で通信される
- ステートレス:前回の通信内容を覚えていない
- リクエスト・レスポンス型:必ずリクエストとレスポンスのペアで動作
実際にあなたがブラウザで開いているこのページも、F12キーを押してブラウザの開発者ツールを開いてみると、実際にどのようなHTTP通信が行われているかを確認できます。
以下はunityroomというサイトを開発者ツールで開いたときに見える、どんな通信をしているかの内容です。

ですが純粋なHTTP通信は、現代ではほとんど使われることはありません。なぜなら、純粋なHTTP通信には大きなセキュリティの問題があるからです。
たまに怪しいサイトを開くと以下のような表示が出ることがありますよね?
これは大体、後述するセキュアなHTTPS通信ではない、純粋なHTTP通信を行なっているサイトに表示されます。(他にも条件はあるみたいですが)

HTTP通信の最大の問題は、すべての通信内容が平文(暗号化されていない状態)で送信されることです。
例えば、フリーWiFiで、純粋なHTTP通信をしようものなら、カンタンにあなたがサイトで入力したユーザ情報やパスワードなどを第三者が読み取れてしまうでしょう。
そこで、実際には、クライアントからサーバへの通信は、通信内容が保護されたHTTPS通信を行うのが一般的です。HTTPS通信の場合、URLの冒頭がhttp
ではなく、https
になります。
HTTPSとはなにか?
HTTPSは、端的にいえば、HTTP通信を暗号化したものです。
HTTP通信では、誰でも読み取れる平文でのやり取りになりますが、HTTPS通信では、通信の内容が暗号化されます。そのため、ユーザのログイン情報や認証情報などは絶対にHTTPS通信で行う必要があります。
ちなみに、ブラウザでHTTPSのURLにアクセスすると、URLバーに鍵マーク🔒が表示されます。

ただし、HTTPS通信を行うためには、事前にサーバ側の設定を行う必要があります。
クラウドのサーバサービスであれば、デフォルトで設定されているか、設定方法の記述が必ずどこかにあるはずです。
クライアント側からアクセスするときは、エンドポイントのURLが、http
始まりではなく、https
始まりになっているか、しっかりとチェックしましょう。
よりセキュリティの高いHTTP通信を行うにはどうしたらよいか?
ここまでで、HTTPSによって通信内容が暗号化されることを書きました。しかし、HTTPSだけでは「完全に安全」とは言えません。
なぜなら、HTTPSは「通信の盗聴」は防げますが、「誰がアクセスしているか」までは保証しないからです。
例えば、第三者があなたになりすまし、HTTPS通信を使ってあなたの代わりにスコア送信用のAPIを送信して、あなたのスコアを書き換えるといったことは出来てしまいます。
このような不正行為を防ぐには、サーバにアクセスをしにいっているクライアントが正当であることを担保するための、「アクセストークン認証」であったり、「OAuthを使ったログイン」などを使うのが一般的です。
アクセストークン認証
アクセストークン認証は、APIにアクセスしてきたユーザが、正当なユーザーであることを証明する仕組みです。
アクセストークンによる認証は、基本的に以下のような手順で行われます。
1.ログイン処理・トークンの保存
- ユーザーがID、パスワードなどでログインを行います。
ログインに成功し、サーバ側でユーザー情報が正しいと判断された場合に、アクセストークン(と、必要に応じてリフレッシュトークン)を発行し、クライアント側にレスポンスとして返します。 - クライアント(Unityクライアントなど)側では、受け取ったアクセストークンをアプリのメモリの中に保持しておきます。

2.APIアクセス時にトークンを付与して送信
アクセストークンを持っている状態というのは「正当な通信の送り主の証明書」を持っているのと同じような意味です。
API通信を行う際には、クライアントからアクセストークンといっしょにリクエストを送信することで、サーバ側は、それが正当な通信であると判断することが出来ます。

一言でまとめると、アクセストークンは正当な通信であることを担保するための証明書です。
アクセストークンには基本的に有効期限があり、たとえばGoogleでは約1時間など、短めに設定されていることが多いです。(自前で発行する場合は自由に設定できます)
そのため、アクセストークンの不正利用を検知されたらすぐに無効にできたり、一定時間で自動で無効にする、といったことも可能です。
アクセストークンを使った通信は、セキュリティの高い通信方法と言えるわけです。
また、アクセストークンでの認証の派生版に、OAuthを使ったログインというものもあります。
↓のような画面が出る時に使われる認証の仕組みです。


食べログでGoogleを使ってログインする流れを例にざっくりと。
OAuthを使った認証の流れは以下のとおりです。
(1)GoogleのIDでログイン
(2)このとき、ログインに成功+ユーザ側で連携を許諾するとGoogleが認可コードを発行
(3) この認可コードを、サーバ側(例:食べログのバックエンド)からGoogleに送ると、Google側が保持しているユーザ情報を取得することができます。
海外のゲームなどでは特に外部サービスでのログイン方法を多く用意しているものを見る気がします。(かつてFacebookでしかログイン出来ないゲームがあって驚いたことがあります...)
CORS(Cross-Origin Resource Sharing)
最後に、ブラウザゲーム限定の話のため、少しピンポイントですが、セキュリティという観点で、CORSという概念についても知っておくと役に立つかもしれません。
ブラウザには「異なるドメイン間の通信を制限する」というセキュリティ機能があります。
例えば:
- ゲームのURL:
https://my-game.com
- APIサーバー:
https://api.my-game.com
これらは「異なるドメイン」と判断され、通常はブラウザが通信をブロックします。このブロッキングする仕組みがCORSです。

なぜブロックされるのか?
悪意のあるサイトが、勝手に他のサイトのデータを取得することを防ぐためです。
たとえば、あなたが自分のゲームからサーバにアクセスするためのAPIを開発したとします。
本来そのAPIは、あなたのゲームが配置されているWebサイトからのみ呼び出したいですよね。
ですが、悪意のある第三者がそのAPIを勝手に呼び出してしまい、あなたのサーバの通信料がとんでもないことになっていた、ということが起こってしまう可能性があります。
そこで、どのドメインからサーバにアクセスするかを限定する仕組みがCORSです。サーバ側で、許可ドメインを登録しておくと、特定のドメインからの通信以外はブロッキングされます。
デフォルトの挙動でそうなっているので、サーバ側で何も設定をしないとCORSブロッキングに遭遇することになります。

モバイルのネイティブアプリや、デスクトップゲームであればあまり意識する必要はないのですが、ブラウザゲームを開発する際は、CORSの設定が非常に重要になりますので、覚えておくと良いと思います。
(私はこのCORSにこれまでとっても苦しめられてきました...。)
CORSのエラーは通常、ブラウザの開発者ツール(ブラウザ開いている状態でF12)で確認することが出来ます。
まとめ
あらためて、重要なワードをリストアップしました。
・HTTP通信/HTTPS通信
・アクセストークン(とOAuth)
・CORS
自分と身内だけで遊ぶゲームであれば、セキュリティを意識する必要はありませんが、世に出す製品のレベルになってくると、こういったセキュリティ対策は必要になります。
セキュリティ対策は、ゲーム体験には一切寄与しないのに、概念が難しく実装が面倒、という厄介な存在です。
バックエンド系の外部サービス(PlayFabなど)であれば、こういった認証周りの実装や、セキュリティをしっかりとサポートしてくれるので、めんどいなぁと感じたら外部サービスに頼ってしまうのも手ですね。
それでは素敵なゲーム制作ライフを!
コメント