ニフティクラウド mobile backendではiOS/Android/JavaScript SDKを提供しています。いずれのSDKにおいてもアプリケーションキーとクライアントキーの2つでアクセスする仕組みになっています。
そのためWebアプリケーションではHTMLまたはJavaScriptソース中にアプリケーションキー、クライアントキーの両方を記述するため、そのまま公開するのはセキュリティ上好ましくありません。
そこでサーバサイドの仕組みをちょっとだけ使ってJavaScript SDKでも安全にニフティクラウド mobile backendにアクセスできるようにしてみたいと思います。
仕組み
現在の仕組みは簡単に言うと次のようになっています。
それを
JavaScript SDKの修正
2014年06月現在、JavaScript SDKの最新版は1.2.1となっています。まずこちらを修正します。具体的には署名を生成している部分、 NCMB._createSignature になります。
こちらの処理の最後の部分、署名を生成している部分を変更します。
var hash = CryptoJS.HmacSHA256(forEncodeString, _clientKey); var signature = CryptoJS.enc.Base64.stringify(hash); return signature;
このSHA256でハッシュ化している部分においてクライアントキーが使われています。ここをJavaScriptではなく、サーバサイドに置き換えます。
return NCMB._ajax( null, null, "POST", "/sign", {forEncodeString: forEncodeString}, "", "");
このようにすることで署名する文字列である forEncodeString を自前のサーバに送信します。返却値として、署名された文字列が受け取れることを期待します。POSTにしているのは外部のサーバから実行されないようにするためです。
後は生成された署名を受け取った後の処理や、クライアントキーがないことによるエラー判定を除外します。
サーバ(Sinatra)
サーバの処理としてはハッシュ化し、Base64でエンコードするだけです。今回はSinatraの例を紹介しますが、大抵のプログラミング言語で簡単に書けると思います。
set :root, File.dirname(__FILE__) set :public_folder, Proc.new { File.join(root, "public") } post '/sign' do content_type :json CLIENT_KEY = 'your_client_key' json = JSON.parse(request.body.read) {signature: Base64.encode64(OpenSSL::HMAC.digest(OpenSSL::Digest::Digest.new('sha256'), CLIENT_KEY, json["forEncodeString"])).strip()}.to_json end
受け取った文字列をサーバ側にしかないクライアントキーでハッシュにし、それをBase64エンコードします。後はできあがった文字列をJSONでWebブラウザに返しています。
デモ
では実際に試してみます。HTMLは次のようになります。
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <script src="javascripts/ncmb-1.2.1.js"></script> <script type="text/javascript"> NCMB.initialize("application_key"); </script>
アプリケーションキーのみで初期化しています。
実際の使い方はサンプルにある通りで変わりません。
var TestClass = NCMB.Object.extend("TestClass"); var testClass = new TestClass(); var query = new NCMB.Query(TestClass); query.equalTo("message", "test"); query.find({ success: function(results) { if (results[0] != null){ alert(results[0].get("message")); } else { testClass.set("message", "Hello, NCMB!"); testClass.save(); console.log("Saved!"); } } });
実行結果は次のようになります。
ということはスマートフォンアプリと共通のアプリケーションを使ってチャットをしたり、JavaScriptだけでサーバサイドへのデータ保存を含めた高度なWebアプリケーションが開発できるようになるということです。
また、サーバサイドの処理は見ての通り簡単ですので、既存のWebサーバに組み込んで使うこともできるでしょう。
今回のコードはGitHubへアップしてあります。ぜひ参考にしてください。