لمساعدتك في تأكيد نوايا المستخدمين عند بدء معاملة حساسة، مثل إجراء عملية دفع، تتيح لك الأجهزة المتوافقة التي تعمل بالإصدار 9 من نظام التشغيل Android (المستوى 28 من واجهة برمجة التطبيقات) أو الإصدارات الأحدث استخدام ميزة "التأكيد المحمي في Android". عند استخدام سير العمل هذا، يعرض تطبيقك طلبًا للمستخدم يطلب منه الموافقة على بيان قصير يؤكّد من جديد نيّته إكمال المعاملة الحسّاسة.
إذا وافق المستخدم على البيان، يمكن لتطبيقك استخدام مفتاح من Android Keystore لتوقيع الرسالة المعروضة في مربّع الحوار. يشير التوقيع، بمستوى ثقة عالٍ جدًا، إلى أنّ المستخدم قد اطّلع على البيان ووافق عليه.
تنبيه: لا توفّر ميزة "التأكيد المحمي على Android" قناة آمنة للمعلومات للمستخدم. لا يمكن لتطبيقك تقديم أي ضمانات بشأن الحفاظ على سرية البيانات تتجاوز تلك التي يوفّرها نظام التشغيل Android. على وجه الخصوص، لا تستخدِم سير العمل هذا لعرض معلومات حسّاسة لا تعرضها عادةً على جهاز المستخدم.
بعد أن يؤكّد المستخدم الرسالة، يتم ضمان سلامة الرسالة، ولكن يجب أن يظل تطبيقك يستخدم ترميز البيانات أثناء النقل لحماية سرية الرسالة الموقّعة.
لإتاحة تأكيد المستخدم بدرجة عالية من الموثوقية في تطبيقك، أكمِل الخطوات التالية:
إنشاء مفتاح توقيع غير متماثل باستخدام الفئة
KeyGenParameterSpec.Builder
عند إنشاء المفتاح، مرِّرtrue
إلىsetUserConfirmationRequired()
. عليك أيضًا استدعاءsetAttestationChallenge()
، مع تمرير قيمة تحدّي مناسبة تقدّمها الجهة المعتمِدة.سجِّل المفتاح الذي تم إنشاؤه حديثًا وشهادة التصديق الخاصة به لدى الجهة المعنية المناسبة.
أرسِل تفاصيل المعاملة إلى الخادم واطلب منه إنشاء كائن ثنائي كبير (BLOB) من البيانات الإضافية وإرجاعه. قد تتضمّن البيانات الإضافية البيانات التي سيتم تأكيدها أو تلميحات التحليل، مثل لغة سلسلة الطلب.
للحصول على تنفيذ أكثر أمانًا، يجب أن يحتوي كائن BLOB على قيمة عشوائية مشفّرة للحماية من هجمات إعادة الإرسال ولتوضيح المعاملات.
اضبط العنصر
ConfirmationCallback
الذي يُعلم تطبيقك عندما يقبل المستخدم الطلب الذي يظهر في مربّع حوار تأكيد:Kotlin
class MyConfirmationCallback : ConfirmationCallback() { override fun onConfirmed(dataThatWasConfirmed: ByteArray?) { super.onConfirmed(dataThatWasConfirmed) // Sign dataThatWasConfirmed using your generated signing key. // By completing this process, you generate a signed statement. } override fun onDismissed() { super.onDismissed() // Handle case where user declined the prompt in the // confirmation dialog. } override fun onCanceled() { super.onCanceled() // Handle case where your app closed the dialog before the user // responded to the prompt. } override fun onError(e: Exception?) { super.onError(e) // Handle the exception that the callback captured. } }
Java
public class MyConfirmationCallback extends ConfirmationCallback { @Override public void onConfirmed(@NonNull byte[] dataThatWasConfirmed) { super.onConfirmed(dataThatWasConfirmed); // Sign dataThatWasConfirmed using your generated signing key. // By completing this process, you generate a signed statement. } @Override public void onDismissed() { super.onDismissed(); // Handle case where user declined the prompt in the // confirmation dialog. } @Override public void onCanceled() { super.onCanceled(); // Handle case where your app closed the dialog before the user // responded to the prompt. } @Override public void onError(Throwable e) { super.onError(e); // Handle the exception that the callback captured. } }
إذا وافق المستخدم على مربع الحوار، سيتم استدعاء الدالة
onConfirmed()
.dataThatWasConfirmed
BLOB هو بنية بيانات CBOR تحتوي، من بين تفاصيل أخرى، على نص الطلب الذي ظهر للمستخدم بالإضافة إلى البيانات الإضافية التي مرّرتها إلى أداة إنشاءConfirmationPrompt
. استخدِم المفتاح الذي تم إنشاؤه سابقًا لتوقيعdataThatWasConfirmed
BLOB، ثم أرسِل هذا BLOB مع التوقيع وتفاصيل المعاملة إلى الجهة المعتمِدة.للاستفادة بشكل كامل من ضمان الأمان الذي توفّره ميزة "التأكيد المحمي" من Android، يجب أن تتّخذ الجهة المعتمِدة الخطوات التالية عند تلقّي رسالة موقَّعة:
- تحقَّق من التوقيع على الرسالة بالإضافة إلى سلسلة شهادات الإثبات لمفتاح التوقيع.
- تأكَّد من ضبط العلامة
TRUSTED_CONFIRMATION_REQUIRED
في شهادة التصديق، ما يشير إلى أنّ مفتاح التوقيع يتطلّب تأكيدًا من مستخدم موثوق به. إذا كان مفتاح التوقيع هو مفتاح RSA، تأكَّد من أنّه لا يتضمّن السمةPURPOSE_ENCRYPT
أوPURPOSE_DECRYPT
. - تحقَّق من
extraData
للتأكّد من أنّ رسالة التأكيد هذه مرتبطة بطلب جديد ولم تتم معالجتها بعد. تحمي هذه الخطوة من هجمات إعادة الإرسال. - حلِّل
promptText
للحصول على معلومات حول الإجراء أو الطلب الذي تم تأكيده. تذكَّر أنّpromptText
هو الجزء الوحيد من الرسالة الذي أكّده المستخدم. يجب ألا يفترض الطرف المعتمِد أبدًا أنّ البيانات التي سيتم تأكيدها والمضمّنة فيextraData
تتطابق معpromptText
.
أضِف منطقًا مشابهًا لما هو موضّح في مقتطف الرمز التالي لعرض مربّع الحوار نفسه:
Kotlin
// This data structure varies by app type. This is an example. data class ConfirmationPromptData(val sender: String, val receiver: String, val amount: String) val myExtraData: ByteArray = byteArrayOf() val myDialogData = ConfirmationPromptData("Ashlyn", "Jordan", "$500") val threadReceivingCallback = Executor { runnable -> runnable.run() } val callback = MyConfirmationCallback() val dialog = ConfirmationPrompt.Builder(context) .setPromptText("${myDialogData.sender}, send ${myDialogData.amount} to ${myDialogData.receiver}?") .setExtraData(myExtraData) .build() dialog.presentPrompt(threadReceivingCallback, callback)
Java
// This data structure varies by app type. This is an example. class ConfirmationPromptData { String sender, receiver, amount; ConfirmationPromptData(String sender, String receiver, String amount) { this.sender = sender; this.receiver = receiver; this.amount = amount; } }; final int MY_EXTRA_DATA_LENGTH = 100; byte[] myExtraData = new byte[MY_EXTRA_DATA_LENGTH]; ConfirmationPromptData myDialogData = new ConfirmationPromptData("Ashlyn", "Jordan", "$500"); Executor threadReceivingCallback = Runnable::run; MyConfirmationCallback callback = new MyConfirmationCallback(); ConfirmationPrompt dialog = (new ConfirmationPrompt.Builder(getApplicationContext())) .setPromptText("${myDialogData.sender}, send ${myDialogData.amount} to ${myDialogData.receiver}?") .setExtraData(myExtraData) .build(); dialog.presentPrompt(threadReceivingCallback, callback);
مراجع إضافية
لمزيد من المعلومات حول ميزة "التأكيد المحمي على Android"، يُرجى الاطّلاع على المراجع التالية.