با مجموعهها، منظم بمانید
ذخیره و طبقهبندی محتوا براساس اولویتهای شما.
برای کمک به تأیید نیت کاربران هنگام شروع تراکنش حساس، مانند پرداخت، دستگاههای پشتیبانیشده دارای Android 9 (سطح API 28) یا بالاتر به شما امکان میدهند از تأیید محافظت شده Android استفاده کنید. هنگام استفاده از این گردش کار، برنامه شما درخواستی را به کاربر نمایش میدهد که از او میخواهد بیانیه کوتاهی را تأیید کند که مجدداً قصد آنها را برای تکمیل تراکنش حساس تأیید میکند.
اگر کاربر بیانیه را بپذیرد، برنامه شما میتواند از کلید Android Keystore برای امضای پیام نشان داده شده در کادر گفتگو استفاده کند. امضا با اطمینان بسیار بالا نشان می دهد که کاربر بیانیه را دیده و با آن موافقت کرده است.
احتیاط: تأیید محافظت شده Android یک کانال اطلاعاتی امن برای کاربر فراهم نمی کند. برنامه شما نمیتواند ضمانتهای محرمانهای را فراتر از ضمانتهایی که پلتفرم Android ارائه میدهد، در نظر بگیرد. به ویژه، از این گردش کار برای نمایش اطلاعات حساسی که معمولاً در دستگاه کاربر نشان نمیدهید استفاده نکنید.
پس از اینکه کاربر پیام را تأیید کرد، یکپارچگی پیام تضمین می شود، اما برنامه شما همچنان باید از رمزگذاری انتقال داده برای محافظت از محرمانه بودن پیام امضا شده استفاده کند.
برای ارائه پشتیبانی از تأیید کاربر با اطمینان بالا در برنامه خود، مراحل زیر را انجام دهید:
کلید تازه تولید شده و گواهی تایید کلید خود را نزد طرف متکی مناسب ثبت کنید.
جزئیات تراکنش را به سرور خود ارسال کنید و از آن بخواهید یک شی بزرگ باینری (BLOB) از داده های اضافی را تولید و برگرداند. دادههای اضافی ممکن است شامل دادههایی باشد که باید تأیید شوند یا نکات تجزیهکننده، مانند محل رشته اعلان.
برای اجرای ایمن تر، BLOB باید حاوی یک nonce رمزنگاری برای محافظت در برابر حملات مجدد و رفع ابهام تراکنش ها باشد.
شی ConfirmationCallback را تنظیم کنید که وقتی کاربر درخواست نشان داده شده در گفتگوی تأیید را پذیرفت به برنامه شما اطلاع می دهد:
کاتلین
classMyConfirmationCallback:ConfirmationCallback(){overridefunonConfirmed(dataThatWasConfirmed:ByteArray?){super.onConfirmed(dataThatWasConfirmed)// Sign dataThatWasConfirmed using your generated signing key.// By completing this process, you generate a signed statement.}overridefunonDismissed(){super.onDismissed()// Handle case where user declined the prompt in the// confirmation dialog.}overridefunonCanceled(){super.onCanceled()// Handle case where your app closed the dialog before the user// responded to the prompt.}overridefunonError(e:Exception?){super.onError(e)// Handle the exception that the callback captured.}}
جاوا
publicclassMyConfirmationCallbackextendsConfirmationCallback{@OverridepublicvoidonConfirmed(@NonNullbyte[]dataThatWasConfirmed){super.onConfirmed(dataThatWasConfirmed);// Sign dataThatWasConfirmed using your generated signing key.// By completing this process, you generate a signed statement.}@OverridepublicvoidonDismissed(){super.onDismissed();// Handle case where user declined the prompt in the// confirmation dialog.}@OverridepublicvoidonCanceled(){super.onCanceled();// Handle case where your app closed the dialog before the user// responded to the prompt.}@OverridepublicvoidonError(Throwablee){super.onError(e);// Handle the exception that the callback captured.}}
اگر کاربر دیالوگ را تأیید کند، فراخوانی onConfirmed() فراخوانی می شود. dataThatWasConfirmed BLOB یک ساختار داده CBOR است که شامل جزییات دیگر، متن درخواستی است که کاربر مشاهده کرده و همچنین دادههای اضافی که شما به سازنده ConfirmationPrompt ارسال کردهاید. از کلید ایجاد شده قبلی برای امضای dataThatWasConfirmed BLOB استفاده کنید، سپس این BLOB را به همراه جزئیات امضا و تراکنش به طرف متکی برگردانید.
برای استفاده کامل از تضمین امنیتی که Android Protected Confirmation ارائه میدهد، طرف متکی باید پس از دریافت پیام امضا شده مراحل زیر را انجام دهد:
امضای روی پیام و همچنین زنجیره گواهی گواهی کلید امضا را بررسی کنید.
بررسی کنید که گواهی گواهی دارای پرچم TRUSTED_CONFIRMATION_REQUIRED باشد، که نشان میدهد کلید امضا به تأیید کاربر مورد اعتماد نیاز دارد. اگر کلید امضا یک کلید RSA است، بررسی کنید که ویژگی PURPOSE_ENCRYPT یا PURPOSE_DECRYPT را نداشته باشد.
extraData را بررسی کنید تا مطمئن شوید که این پیام تأیید متعلق به یک درخواست جدید است و هنوز پردازش نشده است. این مرحله از حملات تکراری محافظت می کند.
برای اطلاعات مربوط به اقدام یا درخواست تایید شده، promptText را تجزیه کنید. به یاد داشته باشید که promptText تنها بخشی از پیام است که کاربر واقعاً تأیید کرده است. طرف متکی هرگز نباید فرض کند که دادههای مورد تأیید موجود در extraData با promptText مطابقت دارد.
منطقی مشابه آنچه در قطعه کد زیر نشان داده شده است را برای نمایش خود گفتگو اضافه کنید:
کاتلین
// This data structure varies by app type. This is an example.dataclassConfirmationPromptData(valsender:String,valreceiver:String,valamount:String)valmyExtraData:ByteArray=byteArrayOf()valmyDialogData=ConfirmationPromptData("Ashlyn","Jordan","$500")valthreadReceivingCallback=Executor{runnable->runnable.run()}valcallback=MyConfirmationCallback()valdialog=ConfirmationPrompt.Builder(context).setPromptText("${myDialogData.sender}, send${myDialogData.amount} to${myDialogData.receiver}?").setExtraData(myExtraData).build()dialog.presentPrompt(threadReceivingCallback,callback)
جاوا
// This data structure varies by app type. This is an example.classConfirmationPromptData{Stringsender,receiver,amount;ConfirmationPromptData(Stringsender,Stringreceiver,Stringamount){this.sender=sender;this.receiver=receiver;this.amount=amount;}};finalintMY_EXTRA_DATA_LENGTH=100;byte[]myExtraData=newbyte[MY_EXTRA_DATA_LENGTH];ConfirmationPromptDatamyDialogData=newConfirmationPromptData("Ashlyn","Jordan","$500");ExecutorthreadReceivingCallback=Runnable::run;MyConfirmationCallbackcallback=newMyConfirmationCallback();ConfirmationPromptdialog=(newConfirmationPrompt.Builder(getApplicationContext())).setPromptText("${myDialogData.sender}, send ${myDialogData.amount} to ${myDialogData.receiver}?").setExtraData(myExtraData).build();dialog.presentPrompt(threadReceivingCallback,callback);
منابع اضافی
برای اطلاعات بیشتر در مورد تأیید محافظت شده Android، به منابع زیر مراجعه کنید.
محتوا و نمونه کدها در این صفحه مشمول پروانههای توصیفشده در پروانه محتوا هستند. جاوا و OpenJDK علامتهای تجاری یا علامتهای تجاری ثبتشده Oracle و/یا وابستههای آن هستند.
تاریخ آخرین بهروزرسانی 2025-08-27 بهوقت ساعت هماهنگ جهانی.
[null,null,["تاریخ آخرین بهروزرسانی 2025-08-27 بهوقت ساعت هماهنگ جهانی."],[],[],null,["To help you confirm users' intentions when they initiate a sensitive\ntransaction, such as making a payment, supported devices that run Android 9 (API\nlevel 28) or higher let you use Android Protected Confirmation. When using this\nworkflow, your app displays a prompt to the user, asking them to approve a short\nstatement that reaffirms their intent to complete the sensitive transaction.\n\nIf the user accepts the statement, your app can use a key from Android Keystore\nto sign the message shown in the dialog. The signature indicates, with very high\nconfidence, that the user has seen the statement and has agreed to it. \n**Caution:**Android Protected Confirmation doesn't provide a\nsecure information channel for the user. Your app can't assume any\nconfidentiality guarantees beyond those that the Android platform offers. In\nparticular, don't use this workflow to display sensitive information that you\nwouldn't ordinarily show on the user's device.\n\nAfter the user confirms the message, the message's integrity is assured,\nbut your app must still use data-in-transit encryption to protect the\nconfidentiality of the signed message.\n\nTo provide support for high-assurance user confirmation in your app, complete\nthe following steps:\n\n1. [Generate an asymmetric signing key](/training/articles/keystore#GeneratingANewPrivateKey)\n using the\n [`KeyGenParameterSpec.Builder`](/reference/android/security/keystore/KeyGenParameterSpec.Builder)\n class. When creating the key, pass `true` into\n [`setUserConfirmationRequired()`](/reference/android/security/keystore/KeyGenParameterSpec.Builder#setUserConfirmationRequired(boolean)).\n Also, call [`setAttestationChallenge()`](/reference/android/security/keystore/KeyGenParameterSpec.Builder#setAttestationChallenge(byte%5B%5D)),\n passing a suitable challenge value provided by the relying party.\n\n2. Enroll the newly generated key and your key's attestation certificate with\n the appropriate relying party.\n\n3. Send transaction details to your server and have it generate and return a\n binary large object (BLOB) of *extra data*. Extra data might include the\n to-be-confirmed data or parsing hints, such as the locale of the prompt string.\n\n For a more secure implementation, the BLOB must contain a cryptographic\n nonce for protection against\n [replay attacks](https://www.pcmag.com/encyclopedia/term/50439/replay-attack)\n and to disambiguate transactions.\n | **Caution:** If the extra data field includes to-be-confirmed data, the relying party must verify the equivalent data that's sent with the prompt string. Android Protected Confirmation doesn't render the extra data, so your app can't assume that the user confirmed this data.\n4. Set up the\n [`ConfirmationCallback`](/reference/android/security/ConfirmationCallback)\n object that informs your app when the user has accepted the prompt shown in a\n confirmation dialog:\n\n Kotlin \n\n ```kotlin\n class MyConfirmationCallback : ConfirmationCallback() {\n\n override fun onConfirmed(dataThatWasConfirmed: ByteArray?) {\n super.onConfirmed(dataThatWasConfirmed)\n // Sign dataThatWasConfirmed using your generated signing key.\n // By completing this process, you generate a signed statement.\n }\n\n override fun onDismissed() {\n super.onDismissed()\n // Handle case where user declined the prompt in the\n // confirmation dialog.\n }\n\n override fun onCanceled() {\n super.onCanceled()\n // Handle case where your app closed the dialog before the user\n // responded to the prompt.\n }\n\n override fun onError(e: Exception?) {\n super.onError(e)\n // Handle the exception that the callback captured.\n }\n }\n ```\n\n Java \n\n ```java\n public class MyConfirmationCallback extends ConfirmationCallback {\n\n @Override\n public void onConfirmed(@NonNull byte[] dataThatWasConfirmed) {\n super.onConfirmed(dataThatWasConfirmed);\n // Sign dataThatWasConfirmed using your generated signing key.\n // By completing this process, you generate a signed statement.\n }\n\n @Override\n public void onDismissed() {\n super.onDismissed();\n // Handle case where user declined the prompt in the\n // confirmation dialog.\n }\n\n @Override\n public void onCanceled() {\n super.onCanceled();\n // Handle case where your app closed the dialog before the user\n // responded to the prompt.\n }\n\n @Override\n public void onError(Throwable e) {\n super.onError(e);\n // Handle the exception that the callback captured.\n }\n }\n ```\n\n If the user approves the dialog, the `onConfirmed()` callback is\n called. The `dataThatWasConfirmed` BLOB is a\n [CBOR data structure](http://cbor.io/) that contains,\n among other details, the prompt text that the user saw as well as the extra\n data that you passed into the\n [`ConfirmationPrompt`](/reference/android/security/ConfirmationPrompt)\n builder. Use the previously created key to sign the\n `dataThatWasConfirmed` BLOB, then pass this BLOB, along with the\n signature and transaction details, back to the relying party.\n | **Note:** Because the key was created using [`setUserConfirmationRequired()`](/reference/android/security/keystore/KeyGenParameterSpec.Builder#setUserConfirmationRequired(boolean)), it can only be used to sign data that's returned in the `dataThatWasConfirmed` parameter. Attempting to sign any other kind of data fails.\n\n To make full use of the security assurance that Android Protected\n Confirmation offers, the relying party must perform the following steps upon\n receiving a signed message:\n 1. Check the signature over the message as well as the attestation certificate chain of the signing key.\n 2. Check that the attestation certificate has the `TRUSTED_CONFIRMATION_REQUIRED` flag set, which indicates that the signing key requires trusted user confirmation. If the signing key is an RSA key, check that it doesn't have the [`PURPOSE_ENCRYPT`](/reference/android/security/keystore/KeyProperties#PURPOSE_ENCRYPT) or [`PURPOSE_DECRYPT`](/reference/android/security/keystore/KeyProperties#PURPOSE_DECRYPT) property.\n 3. Check `extraData` to make sure that this confirmation message belongs to a new request and hasn't been processed yet. This step protects against replay attacks.\n 4. Parse the `promptText` for information about the confirmed action or request. Remember that the `promptText` is the only part of the message that the user actually confirmed. The relying party must never assume that to-be confirmed data included in `extraData` corresponds to the `promptText`.\n5. Add logic similar to that shown in the following code snippet to display the\n dialog itself:\n\n Kotlin \n\n ```kotlin\n // This data structure varies by app type. This is an example.\n data class ConfirmationPromptData(val sender: String,\n val receiver: String, val amount: String)\n\n val myExtraData: ByteArray = byteArrayOf()\n val myDialogData = ConfirmationPromptData(\"Ashlyn\", \"Jordan\", \"$500\")\n val threadReceivingCallback = Executor { runnable -\u003e runnable.run() }\n val callback = MyConfirmationCallback()\n\n val dialog = ConfirmationPrompt.Builder(context)\n .setPromptText(\"${myDialogData.sender}, send\n ${myDialogData.amount} to\n ${myDialogData.receiver}?\")\n .setExtraData(myExtraData)\n .build()\n dialog.presentPrompt(threadReceivingCallback, callback)\n ```\n\n Java \n\n ```java\n // This data structure varies by app type. This is an example.\n class ConfirmationPromptData {\n String sender, receiver, amount;\n ConfirmationPromptData(String sender, String receiver, String amount) {\n this.sender = sender;\n this.receiver = receiver;\n this.amount = amount;\n }\n };\n final int MY_EXTRA_DATA_LENGTH = 100;\n byte[] myExtraData = new byte[MY_EXTRA_DATA_LENGTH];\n ConfirmationPromptData myDialogData = new ConfirmationPromptData(\"Ashlyn\", \"Jordan\", \"$500\");\n Executor threadReceivingCallback = Runnable::run;\n MyConfirmationCallback callback = new MyConfirmationCallback();\n ConfirmationPrompt dialog = (new ConfirmationPrompt.Builder(getApplicationContext()))\n .setPromptText(\"${myDialogData.sender}, send ${myDialogData.amount} to ${myDialogData.receiver}?\")\n .setExtraData(myExtraData)\n .build();\n dialog.presentPrompt(threadReceivingCallback, callback);\n ```\n | **Note:** The confirmation prompt UI, which consists of a full-screen dialog, isn't customizable. However, the framework takes care of localizing button text for you.\n\nAdditional resources\n\nFor more information about Android Protected Confirmation, consult the following\nresources.\n\nBlogs\n\n- [Android Protected Confirmation: Taking transaction security to the next\n level](https://android-developers.googleblog.com/2018/10/android-protected-confirmation.html)"]]