善良なユーザーが使う分には問題無いと思いますが、悪意あるユーザーがコンソールで「userType = 'admin';」などと入力しただけで管理用メニューが表示されてしまいます。
確かに仰るとおりですね。
コマンド一撃でページの挙動を変更出来るような弱い仕組みにしてはいけません。
ただまぁ、Ajax通信をしっかり見張る仕組みにしてしまえばあまり目くじらを立てる必要がないのも事実ですね。
なぜあまり目くじらを立てる必要がないのか?
バックエンド用のWebフレームワークを使って認証機能を採用すれば良いからです。
Ajax通信は裏でJavaScriptがHTTPリクエストを発射しているだけで、
本質的には普通にブラウザでページを閲覧する行為と代わりありません。
特別な事はしなくてもCookieやセッション機能が利用出来るので、バックエンドで認証機能を実装してしまいましょう。
そしてロールを変更して不正なリクエストを投げたとしても、
毎回DBにちゃんと問い合わせて不正なリクエストは弾く作りにしてください。
つまり、ページ上で不正なJSコードを発行して見かけ上の動作を変更したとしても、
Webアプリ全体で受けられる恩恵は微々たるものであり、
有料ユーザーはプロジェクトを多く作れるみたいな感じでAjax通信に依存する箇所に付加価値をかけていけば突破されるリスクはありません。
他にはどんな視点がある?
自分のサービスの価値をどの程度守らなければならないのか検討してみるのも良いでしょう。
例えば、かの有名な秀丸エディタはパスワードを入力するだけで認証を突破出来る脆弱なシステムです。
しかし、その作者は「学生やフリーソフトウェアの開発者は無料にしてあげたい、パスワードを変えたり電話対応したりするとコストが大変なので実質黙認状態、でもまとまったライセンスを買っていただける方もいらっしゃって幸いです」というゆるい対応をしています。
JSを解析して裏でconsole叩いて変な挙動出来るような人間ならば逆にコンタクトをとっても良いかもしれませんね。
日本的ではないかも知れませんが、引き入れれば優秀なメンバーとして活躍してくれるかもしれません。
JSの裁量が大きいページは?
ロールをちょっと切り替えるだけで引き出せる量が違うから不正されると困るという話であれば、
Webpack等が吐き出すJavaScriptファイル自体をAdmin用・エンドユーザー用に分けてしまっても良いと思います。
Admin用は少しくらい不具合が出ても問題になりにくいのでそんなに問題にはならないと思います。
【追記1への回答】
そもそもブラウザの本質を理解していますか?
ブラウザはただ受け取ったHTML・CSS・JS・画像ファイルを内部的に展開して画面に表示しているだけです。
そしてWebサーバへHTTP通信を行いながらHTML・CSS・JS・画像ファイルをまた受け取る。
これがコマンドラインツールのcurlになった瞬間不正になるわけではありません。
全世界のWebサーバはHTTP通信を行う全てのクライアントが対象だからです。
コンソールからコンポーネントに渡すデータを変えればそのコンポーネントの挙動を変更することとが可能だと思います。
Chromeと普通のWebサイトでも可能です。
デベロッパーツール等を利用さえすれば現状のDOM構造を好き勝手に歪めてリクエスト飛ばせますよね。
サービス提供元がわざわざHTMLを渡して上げてるのは、
この項目に従って回答してくださいね、回答が済んだら○○URLのポストに投函してくださいねというガイドラインです。
クラッカーにはHTMLやJSでいくら頑張っても何の対策にもなりません。
クライアントサイドレンダリングの場合は一旦全て送り、ユーザー側で非表示にさせるといった処理が考えられそうです。
SPAではない既存のWebアプリで
HTML情報上にWebサイトを利用する全てのユーザーの住所や氏名をdisplay: none;
の状態で埋め込んでおいて、
JavaScriptで表示・非表示を切り替える開発者がいますか?
それと同じです。
bundle.js内にはそのユーザーが閲覧しても良い情報しか内包してはいけません。
貴方が考えている「一旦全て送り、ユーザー側で非表示にさせる」というのは
上記の全ユーザーの氏名や住所をJavaScript制御でON・OFFを切り替える発想と同じです。
じゃあどうするのか?
Ajaxでそのユーザの権限下でアクセス出来る情報を別途取得してください。
bundle.jsにはAjax通信の結果(JSON)を解析して、アンケートフォームを作り出すロジックのみを埋め込んでください。
これで質問文にあった「男性に化粧品の情報を公開する」懸念は払拭されます。
「私に紐づくアンケートはある?」ということで、
example.com/api/questionnaires
に向けてAjax通信を行います。
女性の場合だけ化粧品のアンケートを表示したいならば、
きっと認証情報には名前、性別、年齢等の情報はありますよね。
JSON
1[
2 {"name": "化粧品Aは既に利用されていますか?", "candidates": ["はい", "いいえ"]},
3 {"name": "化粧品Aを5点満点で評価してください", "candidates": ["1", "2", "3", "4". "5"]},
4 {"name": "化粧品Aのモニターに参加しますか?", "candidates": ["はい", "いいえ"]},
5 {"name": "化粧品Bは既に利用されていますか?", "candidates": ["はい", "いいえ"]},
6 {"name": "化粧品Bを5点満点で評価してください", "candidates": ["1", "2", "3", "4". "5"]},
7 {"name": "化粧品Bのモニターに参加しますか?", "candidates": ["はい", "いいえ"]},
8]
男性の場合は空の配列を返せば化粧品の情報は送られません。
まぁ、別に男性に化粧品名くらい教えても大丈夫かとは思いますが、認証情報と脳内補完して回答しています。
【追記2への回答】
SPAではややロジックも担当している印象を受けたためこのような質問をしました。
追記1に重複する部分がいくつかありますが、重複する部分は追記1への回答を参照してください。
ユーザーに予め渡す情報量が多いのがSPAので、たしかにそのような懸念はあります。
まずはWebサイト全体で使う全ての情報を割り出し一覧化します。
次に各情報はどのレベルでガードしなければならないかを設定します。
これは公開しても良いだろう…といった情報ならばbundle.jsに含めて表示・非表示を切り替えれば良いですし、
公開出来ない情報は全てAjax通信で別途取りに行く設計にしてください。
あれもこれも非公開にしたければ、相応の数のAjax通信用のURL(エンドポイント)が必要になります。
手間や開発コストも吟味しながら取捨選択を行ってください。
もし認証情報を利用した部分以外、
例えばJSONファイルを展開してアンケートのフォーム部品を生成するロジックを非公開にしたい。
……という意図ならば、もうSPAは諦めてください。
SPAで運営しているWebサイト・Webアプリは全て盗まれるリスクとのトレードオフで運営しています。
ですので、守るべき対象はサーバーに保存する個人情報やプロジェクト情報であり、
そこの部分でマネタイズしているから他社にbundle.jsを盗まれたとしてもダメージは軽微であるという判断を行っているからです。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/03/30 03:40