Trình quản lý thông tin xác thực là một API Jetpack hỗ trợ nhiều phương thức đăng nhập, chẳng hạn như đăng nhập bằng tên người dùng và mật khẩu, khoá truy cập và các giải pháp đăng nhập được liên kết (chẳng hạn như Đăng nhập bằng Google) trong một API duy nhất, từ đó đơn giản hoá quá trình tích hợp cho nhà phát triển.
Hơn nữa, đối với người dùng, Trình quản lý thông tin xác thực sẽ hợp nhất giao diện đăng nhập trên các phương thức xác thực, giúp người dùng đăng nhập vào ứng dụng một cách rõ ràng và dễ dàng hơn, bất kể họ chọn phương thức nào.
Trang này giải thích khái niệm khoá truy cập và các bước triển khai việc hỗ trợ ở phía máy khách cho các giải pháp xác thực (bao gồm cả khoá truy cập) bằng cách sử dụng API Trình quản lý thông tin xác thực. Ngoài ra, bạn cũng có thể truy cập vào một trang Câu hỏi thường gặp riêng để tìm câu trả lời cho những câu hỏi cụ thể và chi tiết hơn.
Ý kiến phản hồi của bạn có vai trò quan trọng trong việc cải thiện API Trình quản lý thông tin xác thực. Hãy chia sẻ mọi vấn đề bạn phát hiện được hoặc các ý tưởng giúp cải thiện API bằng đường liên kết sau:
Giới thiệu về khoá truy cập
Khoá truy cập là phương thức thay thế an toàn và dễ dàng hơn cho mật khẩu. Với khoá truy cập, người dùng có thể đăng nhập vào các ứng dụng và trang web nhờ cảm biến sinh trắc học (chẳng hạn như dùng vân tay hoặc công nghệ nhận dạng khuôn mặt), mã PIN hoặc hình mở khoá. Khoá truy cập này mang lại trải nghiệm đăng nhập liền mạch, giúp người dùng không phải nhớ tên người dùng hoặc mật khẩu.
Khoá truy cập dựa vào WebAuthn (Ứng dụng xác thực người dùng truy cập Internet), một tiêu chuẩn do Liên minh FIDO và tổ chức the World Wide Web Consortium (W3C) cùng phát triển. WebAuthn sử dụng tiêu chuẩn mã hoá khoá công khai để xác thực người dùng. Trang web hoặc ứng dụng mà người dùng đăng nhập vào có thể xem và lưu trữ khoá công khai, nhưng tuyệt đối không nhận được khoá riêng tư. Khoá riêng tư này được giữ bí mật và an toàn. Chính vì khoá này là duy nhất cũng như gắn liền với trang web hoặc ứng dụng, nên khoá truy cập sẽ không thể đánh cắp được, nhờ đó tăng cường bảo mật.
Người dùng có thể sử dụng Trình quản lý thông tin xác thực để tạo khoá truy cập và lưu trữ các khoá đó trong Trình quản lý mật khẩu của Google.
Điều kiện tiên quyết
Để sử dụng Trình quản lý thông tin xác thực, hãy hoàn thành các bước trong phần này.
Sử dụng phiên bản nền tảng gần đây
Hỗ trợ Trình quản lý thông tin xác thực trên Android 4.4 (API cấp 19) trở lên.
Thêm phần phụ thuộc vào ứng dụng
Thêm các phần phụ thuộc sau đây vào tập lệnh bản dựng của mô-đun ứng dụng:
Kotlin
dependencies { implementation("androidx.credentials:credentials:1.2.0-beta04") // optional - needed for credentials support from play services, for devices running // Android 13 and below. implementation("androidx.credentials:credentials-play-services-auth:1.2.0-beta04") }
Groovy
dependencies { implementation "androidx.credentials:credentials:1.2.0-beta04" // optional - needed for credentials support from play services, for devices running // Android 13 and below. implementation "androidx.credentials:credentials-play-services-auth:1.2.0-beta04" }
Giữ nguyên các lớp trong tệp ProGuard
Trong tệp proguard-rules.pro
của mô-đun, hãy thêm các lệnh sau:
-if class androidx.credentials.CredentialManager
-keep class androidx.credentials.playservices.** {
*;
}
Tìm hiểu thêm về cách rút gọn, làm rối mã nguồn và tối ưu hoá ứng dụng.
Thêm tính năng hỗ trợ cho Digital Asset Links (Đường liên kết đến tài sản kỹ thuật số)
Để bật tính năng hỗ trợ khoá truy cập cho ứng dụng Android, hãy liên kết ứng dụng của bạn với một trang web mà ứng dụng đó sở hữu. Bạn có thể khai báo mối liên kết này bằng cách hoàn thành các bước sau:
Tạo tệp JSON chứa Digital Asset Links (Đường liên kết đến tài sản kỹ thuật số). Ví dụ: để khai báo rằng trang web
https://signin.example.com
và ứng dụng Android có tên góicom.example
có thể dùng chung thông tin đăng nhập, hãy tạo một tệp có tênassetlinks.json
với nội dung sau:[ { "relation" : [ "delegate_permission/common.handle_all_urls", "delegate_permission/common.get_login_creds" ], "target" : { "namespace" : "android_app", "package_name" : "com.example.android", "sha256_cert_fingerprints" : [ SHA_HEX_VALUE ] } } ]
Trường
relation
là một mảng gồm một hoặc nhiều chuỗi mô tả mối quan hệ đang được khai báo. Để khai báo rằng các ứng dụng và trang web dùng chung thông tin đăng nhập, hãy chỉ định chuỗidelegate_permission/common.get_login_creds
.Trường
target
là đối tượng chỉ định tài sản mà nội dung khai báo sẽ áp dụng. Sau đây là các trường xác định một trang web:namespace
web
site
URL của trang web, có định dạng
https://domain[:optional_port]
; ví dụ:https://www.example.com
.domain phải đủ điều kiện và phải bỏ qua optional_port khi sử dụng cổng 443 cho HTTPS.
Đích
site
chỉ được là miền gốc: bạn không thể giới hạn liên kết ứng dụng với một thư mục con cụ thể. Đừng thêm một đường dẫn vào URL, chẳng hạn như dấu gạch chéo ở cuối.Miền con không được cân nhắc để khớp: nghĩa là nếu bạn chỉ định domain là
www.example.com
, thì miềnwww.counter.example.com
sẽ không được liên kết với ứng dụng của bạn.Sau đây là các trường xác định một ứng dụng Android:
namespace
android_app
package_name
Tên gói được khai báo trong tệp kê khai của ứng dụng. Ví dụ: com.example.android
sha256_cert_fingerprints
Các vân tay số SHA256 trong chứng chỉ ký của ứng dụng. Lưu trữ tệp JSON chứa Digital Asset Links (Đường liên kết đến tài sản kỹ thuật số) tại vị trí sau trên miền đăng nhập:
https://domain[:optional_port]/.well-known/assetlinks.json
Ví dụ: nếu miền đăng nhập của bạn là
signin.example.com
, hãy lưu trữ tệp JSON tạihttps://signin.example.com/.well-known/assetlinks.json
.Loại MIME cho tệp Digital Asset Link (Đường liên kết đến tài sản kỹ thuật số) phải là JSON. Hãy đảm bảo máy chủ gửi một tiêu đề
Content-Type: application/json
trong phản hồi.Đảm bảo rằng máy chủ lưu trữ cho phép Google truy xuất tệp Digital Asset Links (Đường liên kết đến tài sản kỹ thuật số) của bạn. Nếu bạn có tệp
robots.txt
, tệp đó phải cho phép tác nhân Googlebot truy xuất/.well-known/assetlinks.json
. Hầu hết các trang web chỉ cần cho phép mọi tác nhân tự động truy xuất các tệp trong đường dẫn/.well-known/
để các dịch vụ khác có thể truy cập vào siêu dữ liệu trong những tệp đó:User-agent: * Allow: /.well-known/
Định cấu hình Trình quản lý thông tin xác thực
Để định cấu hình và khởi tạo đối tượng CredentialManager
, hãy thêm logic tương tự như sau:
Kotlin
// Use your app or activity context to instantiate a client instance of // CredentialManager. val credentialManager = CredentialManager.create(context)
Java
// Use your app or activity context to instantiate a client instance of // CredentialManager. CredentialManager credentialManager = CredentialManager.create(context)
Chỉ báo trường thông tin đăng nhập
Trên Android 14 trở lên, bạn có thể dùng thuộc tính isCredential
để chỉ báo trường thông tin đăng nhập, chẳng hạn như trường tên người dùng hoặc mật khẩu. Thuộc tính này cho biết rằng thành phần hiển thị này là một trường thông tin đăng nhập sẽ hoạt động với Trình quản lý thông tin xác thực và nhà cung cấp thông tin đăng nhập bên thứ ba, đồng thời giúp các dịch vụ tự động điền cung cấp nội dung gợi ý tự động điền hiệu quả hơn. Khi ứng dụng sử dụng API Trình quản lý thông tin xác thực, bảng dưới cùng của Trình quản lý thông tin xác thực có thông tin đăng nhập sẽ xuất hiện, và tính năng tự động điền không cần hiện hộp thoại điền tên người dùng hoặc mật khẩu nữa.
Để sử dụng thuộc tính isCredential
, hãy thêm thuộc tính này vào các Thành phần hiển thị liên quan:
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:isCredential="true"
...
/>
Đăng nhập người dùng
Để truy xuất mọi tuỳ chọn mật khẩu và khoá truy cập được liên kết với tài khoản của người dùng, hãy hoàn tất các bước sau:
Khởi tạo các tuỳ chọn xác thực bằng mật khẩu và khoá truy cập:
Kotlin
// Retrieves the user's saved password for your app from their // password provider. val getPasswordOption = GetPasswordOption() // Get passkey from the user's public key credential provider. val getPublicKeyCredentialOption = GetPublicKeyCredentialOption( requestJson = requestJson )
Java
// Retrieves the user's saved password for your app from their // password provider. GetPasswordOption getPasswordOption = new GetPasswordOption(); // Get passkey from the user's public key credential provider. GetPublicKeyCredentialOption getPublicKeyCredentialOption = new GetPublicKeyCredentialOption(requestJson);
Tạo yêu cầu đăng nhập, sử dụng các tuỳ chọn được truy xuất từ bước trước:
Kotlin
val getCredRequest = GetCredentialRequest( listOf(getPasswordOption, getPublicKeyCredentialOption) )
Java
GetCredentialRequest getCredRequest = new GetCredentialRequest.Builder() .addCredentialOption(getPasswordOption) .addCredentialOption(getPublicKeyCredentialOption) .build();
Khởi động quy trình đăng nhập:
Kotlin
coroutineScope.launch { try { val result = credentialManager.getCredential( // Use an activity-based context to avoid undefined system UI // launching behavior. context = activityContext, request = getCredRequest ) handleSignIn(result) } catch (e : GetCredentialException) { handleFailure(e) } } fun handleSignIn(result: GetCredentialResponse) { // Handle the successfully returned credential. val credential = result.credential when (credential) { is PublicKeyCredential -> { val responseJson = credential.authenticationResponseJson // Share responseJson i.e. a GetCredentialResponse on your server to // validate and authenticate } is PasswordCredential -> { val username = credential.id val password = credential.password // Use id and password to send to your server to validate // and authenticate } is CustomCredential -> { // If you are also using any external sign-in libraries, parse them // here with the utility functions provided. if (credential.type == ExampleCustomCredential.TYPE) { try { val ExampleCustomCredential = ExampleCustomCredential.createFrom(credential.data) // Extract the required credentials and complete the authentication as per // the federated sign in or any external sign in library flow } catch (e: ExampleCustomCredential.ExampleCustomCredentialParsingException) { // Unlikely to happen. If it does, you likely need to update the dependency // version of your external sign-in library. Log.e(TAG, "Failed to parse an ExampleCustomCredential", e) } } else { // Catch any unrecognized custom credential type here. Log.e(TAG, "Unexpected type of credential") } } else -> { // Catch any unrecognized credential type here. Log.e(TAG, "Unexpected type of credential") } } }
Java
credentialManager.getCredentialAsync( // Use activity based context to avoid undefined // system UI launching behavior activity, getCredRequest, cancellationSignal, <executor>, new CredentialManagerCallback<GetCredentialResponse, GetCredentialException>() { @Override public void onSuccess(GetCredentialResponse result) { handleSignIn(result); } @Override public void onFailure(GetCredentialException e) { handleFailure(e); } } ); public void handleSignIn(GetCredentialResponse result) { // Handle the successfully returned credential. Credential credential = result.getCredential(); if (credential instanceof PublicKeyCredential) { String responseJson = ((PublicKeyCredential) credential).getAuthenticationResponseJson(); // Share responseJson i.e. a GetCredentialResponse on your server to validate and authenticate } else if (credential instanceof PasswordCredential) { String username = ((PasswordCredential) credential).getId(); String password = ((PasswordCredential) credential).getPassword(); // Use id and password to send to your server to validate and authenticate } else if (credential instanceof CustomCredential) { if (ExampleCustomCredential.TYPE.equals(credential.getType())) { try { ExampleCustomCredential customCred = ExampleCustomCredential.createFrom(customCredential.getData()); // Extract the required credentials and complete the // authentication as per the federated sign in or any external // sign in library flow } catch (ExampleCustomCredential.ExampleCustomCredentialParsingException e) { // Unlikely to happen. If it does, you likely need to update the // dependency version of your external sign-in library. Log.e(TAG, "Failed to parse an ExampleCustomCredential", e); } } else { // Catch any unrecognized custom credential type here. Log.e(TAG, "Unexpected type of credential"); } } else { // Catch any unrecognized credential type here. Log.e(TAG, "Unexpected type of credential"); } }
Ví dụ sau đây cho thấy cách định dạng yêu cầu JSON khi bạn nhận được khoá truy cập:
{
"challenge": "T1xCsnxM2DNL2KdK5CLa6fMhD7OBqho6syzInk_n-Uo",
"allowCredentials": [],
"timeout": 1800000,
"userVerification": "required",
"rpId": "credential-manager-app-test.glitch.me"
}
Ví dụ sau đây cho thấy phản hồi JSON trông như thế nào sau khi bạn nhận được thông tin xác thực khoá công khai:
{
"id": "KEDetxZcUfinhVi6Za5nZQ",
"type": "public-key",
"rawId": "KEDetxZcUfinhVi6Za5nZQ",
"response": {
"clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiVDF4Q3NueE0yRE5MMktkSzVDTGE2Zk1oRDdPQnFobzZzeXpJbmtfbi1VbyIsIm9yaWdpbiI6ImFuZHJvaWQ6YXBrLWtleS1oYXNoOk1MTHpEdll4UTRFS1R3QzZVNlpWVnJGUXRIOEdjVi0xZDQ0NEZLOUh2YUkiLCJhbmRyb2lkUGFja2FnZU5hbWUiOiJjb20uZ29vZ2xlLmNyZWRlbnRpYWxtYW5hZ2VyLnNhbXBsZSJ9",
"authenticatorData": "j5r_fLFhV-qdmGEwiukwD5E_5ama9g0hzXgN8thcFGQdAAAAAA",
"signature": "MEUCIQCO1Cm4SA2xiG5FdKDHCJorueiS04wCsqHhiRDbbgITYAIgMKMFirgC2SSFmxrh7z9PzUqr0bK1HZ6Zn8vZVhETnyQ",
"userHandle": "2HzoHm_hY0CjuEESY9tY6-3SdjmNHOoNqaPDcZGzsr0"
}
}
Quy trình đăng ký
Bạn có thể đăng ký phương thức xác thực cho người dùng bằng khoá truy cập hoặc mật khẩu.
Tạo khoá truy cập
Để giúp người dùng có lựa chọn đăng ký khoá truy cập và dùng khoá truy cập đó cho quá trình xác thực lại, hãy đăng ký thông tin xác thực người dùng bằng cách sử dụng đối tượng CreatePublicKeyCredentialRequest
.
Khi bạn gọi API Trình quản lý thông tin xác thực lần đầu tiên, hãy đặt preferImmediatelyAvailableCredentials
thành true
. Phương thức preferImmediatelyAvailableCredentials
xác định xem bạn có muốn chỉ sử dụng thông tin xác thực có sẵn ngay chứ không sử dụng thông tin xác thực kết hợp để thực hiện yêu cầu này hay không. Nếu là true
, API Trình quản lý thông tin xác thực sẽ không hiển thị mục nhập từ xa nếu không có thông tin đăng nhập. Theo mặc định, giá trị này là false
.
Kotlin
fun createPasskey(requestJson: String, preferImmediatelyAvailableCredentials: Boolean) { val createPublicKeyCredentialRequest = CreatePublicKeyCredentialRequest( // Contains the request in JSON format. Uses the standard WebAuthn // web JSON spec. requestJson = requestJson, // Defines whether you prefer to use only immediately available // credentials, not hybrid credentials, to fulfill this request. // This value is false by default. preferImmediatelyAvailableCredentials = preferImmediatelyAvailableCredentials, ) // Execute CreateCredentialRequest asynchronously to register credentials // for a user account. Handle success and failure cases with the result and // exceptions, respectively. coroutineScope.launch { try { val result = credentialManager.createCredential( // Use an activity-based context to avoid undefined system // UI launching behavior context = activityContext, request = createPublicKeyCredentialRequest, ) handlePasskeyRegistrationResult(result) } catch (e : CreateCredentialException){ handleFailure(e) } } } fun handleFailure(e: CreateCredentialException) { when (e) { is CreatePublicKeyCredentialDomException -> { // Handle the passkey DOM errors thrown according to the // WebAuthn spec. handlePasskeyError(e.domError) } is CreateCredentialCancellationException -> { // The user intentionally canceled the operation and chose not // to register the credential. } is CreateCredentialInterruptedException -> { // Retry-able error. Consider retrying the call. } is CreateCredentialProviderConfigurationException -> { // Your app is missing the provider configuration dependency. // Most likely, you're missing the // "credentials-play-services-auth" module. } is CreateCredentialUnknownException -> ... is CreateCredentialCustomException -> { // You have encountered an error from a 3rd-party SDK. If you // make the API call with a request object that's a subclass of // CreateCustomCredentialRequest using a 3rd-party SDK, then you // should check for any custom exception type constants within // that SDK to match with e.type. Otherwise, drop or log the // exception. } else -> Log.w(TAG, "Unexpected exception type ${e::class.java.name}") } }
Java
public void createPasskey(String requestJson, boolean preferImmediatelyAvailableCredentials) { CreatePublicKeyCredentialRequest createPublicKeyCredentialRequest = // `requestJson` contains the request in JSON format. Uses the standard // WebAuthn web JSON spec. // `preferImmediatelyAvailableCredentials` defines whether you prefer // to only use immediately available credentials, not hybrid credentials, // to fulfill this request. This value is false by default. new CreatePublicKeyCredentialRequest( requestJson, preferImmediatelyAvailableCredentials); // Execute CreateCredentialRequest asynchronously to register credentials // for a user account. Handle success and failure cases with the result and // exceptions, respectively. credentialManager.createCredentialAsync( // Use an activity-based context to avoid undefined system // UI launching behavior requireActivity(), createPublicKeyCredentialRequest, cancellationSignal, executor, new CredentialManagerCallback<CreateCredentialResponse, CreateCredentialException>() { @Override public void onResult(CreateCredentialResponse result) { handleSuccessfulCreatePasskeyResult(result); } @Override public void onError(CreateCredentialException e) { if (e instanceof CreatePublicKeyCredentialDomException) { // Handle the passkey DOM errors thrown according to the // WebAuthn spec. handlePasskeyError(((CreatePublicKeyCredentialDomException)e).getDomError()); } else if (e instanceof CreateCredentialCancellationException) { // The user intentionally canceled the operation and chose not // to register the credential. } else if (e instanceof CreateCredentialInterruptedException) { // Retry-able error. Consider retrying the call. } else if (e instanceof CreateCredentialProviderConfigurationException) { // Your app is missing the provider configuration dependency. // Most likely, you're missing the // "credentials-play-services-auth" module. } else if (e instanceof CreateCredentialUnknownException) { } else if (e instanceof CreateCredentialCustomException) { // You have encountered an error from a 3rd-party SDK. If // you make the API call with a request object that's a // subclass of // CreateCustomCredentialRequest using a 3rd-party SDK, // then you should check for any custom exception type // constants within that SDK to match with e.type. // Otherwise, drop or log the exception. } else { Log.w(TAG, "Unexpected exception type " + e.getClass().getName()); } } } ); }
Định dạng yêu cầu JSON
Sau khi tạo khoá truy cập, bạn phải liên kết khoá truy cập đó với tài khoản của người dùng và lưu trữ khoá công khai của khoá truy cập trên máy chủ của bạn. Đoạn mã sau đây trình bày ví dụ về cách định dạng yêu cầu JSON khi bạn tạo khoá truy cập.
Bài đăng này trên blog về xác thực liền mạch trong ứng dụng sẽ hướng dẫn bạn cách định dạng yêu cầu JSON khi tạo mã xác thực và khi xác thực bằng khoá truy cập. Bài đăng này cũng giải thích lý do mật khẩu không phải là giải pháp xác thực hiệu quả, cùng với cách tận dụng thông tin xác thực sinh trắc học có sẵn, cách liên kết ứng dụng với trang web mà bạn sở hữu, cách tạo mã xác thực và cách xác thực bằng cách sử dụng mã xác thực.
{
"challenge": "nhkQXfE59Jb97VyyNJkvDiXucMEvltduvcrDmGrODHY",
"rp": {
"name": "CredMan App Test",
"id": "credential-manager-app-test.glitch.me"
},
"user": {
"id": "2HzoHm_hY0CjuEESY9tY6-3SdjmNHOoNqaPDcZGzsr0",
"name": "helloandroid@gmail.com",
"displayName": "helloandroid@gmail.com"
},
"pubKeyCredParams": [
{
"type": "public-key",
"alg": -7
},
{
"type": "public-key",
"alg": -257
}
],
"timeout": 1800000,
"attestation": "none",
"excludeCredentials": [],
"authenticatorSelection": {
"authenticatorAttachment": "platform",
"requireResidentKey": true,
"residentKey": "required",
"userVerification": "required"
}
}
Xử lý phản hồi JSON
Đoạn mã sau đây minh hoạ phản hồi JSON mẫu để tạo thông tin xác thực khoá công khai. Tìm hiểu thêm về cách xử lý thông tin xác thực của khoá công khai trả về.
{
"id": "KEDetxZcUfinhVi6Za5nZQ",
"type": "public-key",
"rawId": "KEDetxZcUfinhVi6Za5nZQ",
"response": {
"clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoibmhrUVhmRTU5SmI5N1Z5eU5Ka3ZEaVh1Y01Fdmx0ZHV2Y3JEbUdyT0RIWSIsIm9yaWdpbiI6ImFuZHJvaWQ6YXBrLWtleS1oYXNoOk1MTHpEdll4UTRFS1R3QzZVNlpWVnJGUXRIOEdjVi0xZDQ0NEZLOUh2YUkiLCJhbmRyb2lkUGFja2FnZU5hbWUiOiJjb20uZ29vZ2xlLmNyZWRlbnRpYWxtYW5hZ2VyLnNhbXBsZSJ9",
"attestationObject": "o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YViUj5r_fLFhV-qdmGEwiukwD5E_5ama9g0hzXgN8thcFGRdAAAAAAAAAAAAAAAAAAAAAAAAAAAAEChA3rcWXFH4p4VYumWuZ2WlAQIDJiABIVgg4RqZaJyaC24Pf4tT-8ONIZ5_Elddf3dNotGOx81jj3siWCAWXS6Lz70hvC2g8hwoLllOwlsbYatNkO2uYFO-eJID6A"
}
}
Lưu mật khẩu của người dùng
Nếu người dùng cung cấp tên người dùng và mật khẩu cho luồng xác thực trong ứng dụng, thì bạn có thể đăng ký thông tin xác thực người dùng để dùng cho mục đích xác thực người dùng. Để thực hiện việc này, hãy tạo đối tượng CreatePasswordRequest
:
Kotlin
fun registerPassword(username: String, password: String) { // Initialize a CreatePasswordRequest object. val createPasswordRequest = CreatePasswordRequest(id = username, password = password) // Create credential and handle result. coroutineScope.launch { try { val result = credentialManager.createCredential( // Use an activity based context to avoid undefined // system UI launching behavior. activityContext, createPasswordRequest ) handleRegisterPasswordResult(result) } catch (e: CreateCredentialException) { handleFailure(e) } } }
Java
void registerPassword(String username, String password) { // Initialize a CreatePasswordRequest object. CreatePasswordRequest createPasswordRequest = new CreatePasswordRequest(username, password); // Register the username and password. credentialManager.createCredentialAsync( // Use an activity-based context to avoid undefined // system UI launching behavior requireActivity(), createPasswordRequest, cancellationSignal, executor, new CredentialManagerCallback<CreateCredentialResponse, CreateCredentialException>() { @Override public void onResult(CreateCredentialResponse result) { handleResult(result); } @Override public void onError(CreateCredentialException e) { handleFailure(e); } } ); }
Hỗ trợ khôi phục thông tin đăng nhập
Nếu không còn quyền truy cập vào thiết bị lưu trữ thông tin đăng nhập, thì người dùng có thể khôi phục thông qua bản sao lưu bảo mật trực tuyến. Để tìm hiểu thêm về cách hỗ trợ quá trình khôi phục thông tin đăng nhập, hãy đọc phần có tiêu đề "Khôi phục quyền truy cập hoặc thêm thiết bị mới" trong bài đăng này trên blog: Tính bảo mật của khoá truy cập trong Trình quản lý mật khẩu của Google.
Thêm tính năng hỗ trợ cho các công cụ quản lý mật khẩu bằng URL phổ biến của Điểm cuối khoá truy cập
Để tích hợp liền mạch và đảm bảo khả năng tương thích sau này với các công cụ quản lý thông tin đăng nhập, bạn nên thêm tính năng hỗ trợ các URL phổ biến của Điểm cuối khoá truy cập. Đây là một giao thức mở cho các bên liên kết để chính thức quảng cáo tính năng hỗ trợ khoá truy cập cũng như cung cấp các đường liên kết trực tiếp để đăng ký và quản lý khoá truy cập.
Đối với một bên phụ thuộc tại https://example.com, có một trang web và các ứng dụng dành cho Android và iOS, URL phổ biến sẽ là https://example.com/.well-known/passkey-endpoints
Khi URL được truy vấn, phản hồi phải sử dụng lược đồ sau
{ "enroll": "https://example.com/account/manage/passkeys/create" "manage": "https://example.com/account/manage/passkeys" }
Để mở đường liên kết này ngay trong ứng dụng của bạn thay vì trên web, hãy sử dụng đường liên kết trong ứng dụng Android.
Bạn có thể xem thêm thông tin chi tiết trong công cụ giải thích về URL phổ biến của Điểm cuối khoá truy cập trên GitHub.
Khắc phục các lỗi thường gặp
Bảng sau đây trình bày mã và nội dung mô tả của một vài lỗi thường gặp, đồng thời cung cấp một số thông tin về nguyên nhân gây ra các lỗi đó:
Mã lỗi và nội dung mô tả | Nguyên nhân |
---|---|
Lỗi khi bắt đầu đăng nhập: 16: Phương thức gọi tạm thời bị chặn do có quá nhiều lời nhắc đăng nhập bị huỷ. | Nếu trong quá trình phát triển, bạn gặp phải lỗi thời gian chờ 24 giờ, bạn có thể đặt lại khoảng thời gian đó bằng cách xoá bộ nhớ ứng dụng của Dịch vụ Google Play. Ngoài ra, để bật/tắt thời gian chờ này trên trình mô phỏng hoặc thiết bị kiểm thử, hãy chuyển đến ứng dụng Trình quay số rồi nhập mã sau: |
Lỗi khi bắt đầu đăng nhập: 8: Lỗi nội bộ không xác định. |
|
CreatePublicKeyCredentialDomException: Không xác thực được yêu cầu đến | Mã gói của ứng dụng chưa được đăng ký với máy chủ. Hãy xác thực mã này trong quá trình tích hợp phía máy chủ. |
CreateCredentialUnknownException: Trong quá trình lưu mật khẩu, đã phát hiện phản hồi lỗi mật khẩu từ Cơ chế một lần chạm 16: Bỏ qua quá trình lưu mật khẩu vì có khả năng người dùng được tính năng Tự động điền của Android nhắc | Lỗi này chỉ xảy ra trên Android 13 trở xuống, và chỉ khi Google là nhà cung cấp dịch vụ Tự động điền. Trong trường hợp này, người dùng sẽ thấy lời nhắc thực hiện thao tác lưu từ tính năng Tự động điền, đồng thời mật khẩu sẽ được lưu vào Trình quản lý mật khẩu của Google. Xin lưu ý rằng thông tin đăng nhập được lưu bởi tính năng Tự động điền bằng Google sẽ được chia sẻ hai chiều với API Trình quản lý thông tin xác thực. Do đó, bạn có thể bỏ qua lỗi này một cách an toàn. |
Tài nguyên khác
Để tìm hiểu thêm về API Trình quản lý thông tin xác thực và khoá truy cập, hãy xem các tài nguyên sau:
- Hướng dẫn về trải nghiệm người dùng với khoá truy cập
- Video: Cách giảm sự phụ thuộc vào mật khẩu trong các ứng dụng Android bằng sự hỗ trợ của khoá truy cập
- Lớp học lập trình: Tìm hiểu cách đơn giản hoá quy trình xác thực bằng cách sử dụng API Trình quản lý thông tin xác thực trong ứng dụng Android
- Ứng dụng mẫu: CredentialManager