PWAゲームを開発しネイティブアプリ化までした中での課題と対策
https://gyazo.com/3eab0788e33bf11469cf548643510250
通信量を減らすアセット戦略
4万アセット、1GBくらいある
オフライン戦略
ブラウザ都合で少量しかキャッシュできない
AndroidとChromeであれば?
ストレージ永続化
成立する条件が複雑で厳しい
現実的な対応
Cache-Control対応
すべてをmax-age=31536000(1年)
アセットバージョンの取得例
静的の場合
バージョン付きで埋め込む
動的に組み立てる場合
1. APIレスポンスにアセットバージョンを含める
2. アセットパスとバージョンの対応表を作成して最初に取得
CDNの自動圧縮ではないファイルの場合はgzip圧縮
Content-Encoding: gzip
m4aやwasmは圧縮効率が良い
マスターデータの管理方法
サーバ・クライアントのどちらで管理すべきか?
クライアント
サーバのレスポンスを早く返せる
容量制限あり
保存データの漏洩リスク
サーバー
レスポンスに必要な情報が含まれる
紐付け処理で応答性能が悪くなるかも
レスポンスが肥大化しやすい
レスポンスからの漏洩のリスク
ノックノートはサーバ管理を選択
高速検索方法
アプリケーションサーバ上のメモリにのせる・キャッシュさせる
B+Tree構造で展開
依存データはEager Loadingで取得する
マスターデータの間引き
依存するデータや必要なカラムをうけとってAPIを自動生成させる
APIドキュメントも生成できる
ソースコードや通信内容が見れる中でのチート対策
暗号化処理
アセットの秘匿化
アセットパスの難読化
類推可能だと抜かれるリスクあり
パスの途中にハッシュ値を含める
ローカルに保存したあとだと推測されやすい
パス全体をハッシュ化
ハッシュ化されたあとのパスを使ってデバッグが困難
実際の対策
全体をハッシュ化
全体のハッシュ化はステージング以上の環境に限定
テキストファイルの暗号化
共通鍵暗号方式
暗号化はアセットアップローダ経由
画像の暗号化
スクショやcanvasのキャプチャは許容
オリジナルの画像を抜かれたくないとき
HTMLImageElementを経由するため
WebGLRenderingContext.tex(Sub)Image2DにはImageBitmapを渡せる
XHRで画像データを取得
復号
ImageBitmapに変換
メモリをかなり食うので複数表示時は注意
gl.texImage2D()にImageBitmapを渡す
POST /のbodyに入れて送る
バイナリを圧縮して返すときは圧縮効率が悪い
アプリケーションコードの秘匿化
共通鍵暗号の鍵やロジックを守る
アプリケーションコードを隠蔽する
sourceURLを付与してevalするとSourceMapも使える
ソースコード自体を守る
window.JSONなどのglobalなAPIフックから守る
Chromeのローカルオーバライド
任意のファイルをローカル上に保存しているのに置換できる機能
簡単に処理を書き換えたり任意の処理を追加できる
アプリケーションコード評価前に差し替えられてないかチェック
その後ローカルのJSONを取得
code:js
const json = {};
json.parse = window.JSON.parse;
window.JSON = json;
インゲームロジックを守る
インゲーム
ロジックはサーバで動かしたほうがいいが…
サーバのアプリケーションコードを記述するハードルが高い
ゲームによっては応答速度でUX悪化
ターン制のゲームなので毎ターンサーバと通信して結果を突き合わせる
学び
cgo内で発生したSIGNALはGoからキャッチできない
処理系依存、JSとGoで挙動が違う