Appleが提供する脆弱なアプローチ
サーバーは、次のようにして購入を認証できます。
iPhoneアプリケーションはtransactionReceipt
購入後に受け取ります。iPhoneのbase64でエンコードして( NSDataへのこのオープンソースの追加を使用できます)、サーバーに送信します。(そのまま送信して、検証前にサーバーbase64にエンコードさせることもできます。)
サーバーに、HTTPPOSTを 使用するようにreceipt-data
エンコードされたbase64の単一キーを使用してJSONリクエストを送信してもらいます。(さまざまなサーバー側言語でこれを行う方法については、このサイトを参照してください)transactionReceipt
https://buy.itunes.apple.com/verifyReceipt
サーバーは、2つのキーを持つJSONオブジェクトで応答します。status
これは整数でreceipt
あり、受信が繰り返されます。
ステータスがゼロの場合、レシートは有効です。ゼロ以外の値は、レシートが無効であることを意味します。
Appleのアプローチへの安全な追加
ただし、セキュリティにはいくつかの影響があります。デバイスがレシートに関連付けられていないため、ユーザーは別のユーザーのレシートを使用できます。または、サーバーがレシートの製品IDを確認しないため、ユーザーは別の製品のレシートを使用できます。これが起こらないようにするには、次のことも行う必要があります。
アプリケーションで最初に領収書を受け取ったら、HTTPSやSSLソケットなどの安全なチャネルを介して、デバイスのUUIDと一緒にすぐにサーバーに送信します。どこにも保存せず、メモリに残しておきます。
サーバーで、UUIDとレシートのペアをデータベースに保存します。
デバイスがUUIDとレシートのペアを送信するときは、レシートがまだ使用されていないことをデータベースで確認し、レシートの製品IDを確認して、レシートが実際に製品のものであることを確認します。レシートは単なるJSONオブジェクトであるため、サーバーはbase64からレシートをデコードすることでコンテンツを読み取ることができます。
安全なチャネルを介してデバイスに応答を返し、購入が次のとおりであるかどうかを通知します。
- 新規として認証されました(DBにはなく、有効でした)
- 過去に認証されました(同じUUIDとレシートのペアがすでにDBにありました)
- 製品IDが間違っているため拒否されました
- 別のUUIDでレシートをすでに使用しているため、拒否されました。
レシートはデバイスのメモリにのみ存在し、アプリケーションはデバイスのUUIDを使用し(ジェイルブレイクされたデバイスによってスプーフィングされる可能性があります。コメントを参照)、製品のすべての購入はサーバー上のデバイスのUUIDに安全に記録されます。 ; ユーザーは、他のユーザーの領収書を使用して購入を確認したり、他の製品の領収書を使用したりすることはできません。これを確認するためです。
トランザクションの他の詳細を確認する場合は、領収書から他のフィールドを検証することもできます。たとえば、製品がサブスクリプションである場合は、トランザクションの日付も確認する必要があります。
また、ユーザーはSSL証明書を持っていないため、同じ名前のホストを持つプライベートネットワーク上にデバイスを置いてサーバーのふりをすることはできません。
障害に関する考慮事項
ユーザーのデバイスがレシートを受け取ってからサーバーで確認するまでの間に障害が発生する可能性があるため(たとえば、ユーザーが接続を失った場合、またはサーバーがメンテナンスのためにダウンした場合)、ユーザーに「再承認」を許可する必要があります。再承認は、 (復元されたトランザクションを使用して)ストアからレシートを取得し、これが新規購入であるかのようにサーバーに再送信する必要があります。これを使用する必要はめったにありませんが、ネットワーク障害が発生した場合にユーザーが製品を再購入する手間を省くために利用できる必要があります。
複数のデバイスに関する考慮事項
つまり、ユーザーが複数のデバイスでアプリケーションを使用する場合は、製品を複数回購入する必要があります。これは望ましい効果かもしれませんが、ユーザーがアカウントに関連付けたデバイス間でコンテンツを使用できることを期待している可能性があるため、購入する前にユーザーに通知する必要があります。
レシートにiTunesアカウント情報も含まれている場合、認証ではそれを使用して、ユーザーがすべてのデバイス間でコンテンツを共有できるようにすることができます(ただし、友達は共有できません)。