ゲームのランキング機能でNCMBを使ってくれているアプリはとても多いです。そんな中、データを改ざん(不正なスコアの投入など)を経験した人もいるはずです。
今回はそうした改ざんからアプリデータを防衛する方法を紹介します。
スクリプトを使う
一番良いのはスクリプトを使う方法でしょう。まず管理画面で、スコアが入るクラス(Scoreクラスとします)のパーミッションを設定します。クラスを選択し、 クラスの編集 > パーミッションの設定 と進んでください。
- データの新規作成
adminロールのみ - データの閲覧
全員可
データの更新、削除権限は不要とします。
そしてアプリからはスコアのデータと、何らかのチェックデジット(正常に作成されたとわかるフラグ)を送ります。スコアと入力されたユーザ名の2つから生成する形が良いでしょう。これはクライアント側で実行するコードになります。
サーバ側では、スコア/ユーザ名/チェックデジットの3つを使って検証します。これが問題なければScoreクラスへデータを書き込みます。
メリット
この方法の場合、Scoreクラスという名前がわかったとしても、不正なデータを書き込めません(パーミッション制限)。チェックデジットを生成するアルゴリズムはクライアントサイドにあるので、このコードが漏洩しない限りは安全にスコアを登録できるでしょう。
ACLを使う
スクリプトのが複雑に感じてしまう場合には、ACLを利用する方法もあります。不正なデータを登録するユーザの場合、ACLを気にすることは基本的にないでしょう。ACLをつけずに登録したデータは「誰でも読み書き可能」なデータになります。このデータは次のようなACLになっています。 *
は「誰でも」といった意味になります。
{"*": { "read": true, "write": true }}
ランキングを表示する上で誰でも読み込み可能 {"*": {"read": true}}
は必要になりますが、 "write": true
は不要です。そこで検索条件を指定する時に、write: true
が含まれないデータをターゲットにします。
例えばJavaScript SDKの場合は次のようになります。
各言語向けに書くと、次のようになります。
JavaScript
const res2 = await Score .notEqualTo('acl.*.write', true) .fetchAll();
Swift
var query = NCMBQuery.getQuery(className: "Score") query.where("acl.*.write", notEqualTo: true) query.findInBackground(callback: { result in // 処理を書く })
Unity
NCMBQuery<NCMBObject> query = new NCMBQuery<NCMBObject> ("Score"); query. WhereNotEqualTo ("acl.*.write", true); query.FindAsync ((List<NCMBObject> objList ,NCMBException e) => { if (e != null) { } else { // 検索成功時の処理 foreach (NCMBObject obj in objList) { Debug.Log ("objectId:" + obj.ObjectId); } } });
もちろんアプリ側から正規にデータを登録する際には、書き込み権限を落とした状態で行う必要があります。
メリット
ACLを使った方式は簡易的ではありますが、余計なデータを表示しない効果はあるでしょう。もちろん不正なデータ登録時に書き込みフラグを落として登録されてしまうと、正規のデータと見分けがつかないという問題はあります。
まとめ
mBaaSではREST APIを使ってデータを登録しているので、アプリケーションキーやクライアントキー、そしてクラス名などが分かってしまうと操作される可能性があるでしょう。
改ざんや不正に作成されないようにするためにはスクリプトやクラスのパーミッション、ACLによる制御を行ってください。