开发者控制台

集成A3L身份验证SDK

集成A3L身份验证SDK

请按照本指南将您的应用与A3L身份验证SDK集成。

设置A3L身份验证登录

要将A3L身份验证集成到您的Android应用中,必须配置A3L身份验证并添加启动登录流程的按钮。

初始化A3L身份验证

在登录活动的onCreate()方法中,初始化A3L身份验证,提供从Google API控制台获得的Android客户端ID,如以下代码所示。

try{
    A3LAuth.init(<PREFIX>);
} catch(APIException e) {
    e.printStackTrace();
}

对于使用Google Play服务的设备,默认解决方案是Google Sign-In。对于不使用Google Play服务的设备,默认使用AppAuth。如果希望为用户提供相似的体验,并在所有设备上使用AppAuth作为解决方案,请按以下代码所示来初始化您的应用。

try{
    A3LAuth.init(<PREFIX>, true);
} catch(APIException e) {
    e.printStackTrace();
}

配置A3LSignIn和A3LSignInClient对象

接下来,按照以下步骤配置A3LSignInA3LSignInClient对象。

  1. onCreate()方法中,配置A3L身份验证,以通过A3LSignInOptions对象请求应用所需的用户数据。

    例如,要配置A3L身份验证以请求获取用户的ID和基本个人资料信息,请使用DEFAULT_SIGN_IN参数构建A3LSignInOptions对象。如果还希望请求获取用户的电子邮件地址,请在创建A3LSignInOptions对象时加入requestEmail()选项,如下所示。

     //配置登录以请求获取用户的ID、电子邮件地址和基本
     // 个人资料。ID和基本个人资料包含在DEFAULT_SIGN_IN中。
     A3LSignInOptions a3LSignInOptions = new A3LSignInOptions
                                     .Builder(A3LSignInOptions.DEFAULT_SIGN_IN)
                                     .requestEmail()
                                     .build();
    
  2. onCreate()方法中,使用在上一步中创建的A3LSignInOptions对象中指定的选项,创建A3LSignInClient对象,如以下代码所示。

     //使用上面创建的A3LSignInClient对象
     // 指定的选项来构建A3LSignInClient。
     mA3LSignInClient = A3LSignIn.getClient(this, a3LSignInOptions);
    

检查用户是否已登录

在显示登录流程之前,请使用getLastSignedInAccount()方法来检查用户是否已登录应用。在活动的onStart()方法中,检查用户是否已登录,如此示例所示。

 //如果用户已登录,则检查是否存在现有的登录账户
// A3LSignInAccount将为非null。
A3LSignInAccount account = A3LSignIn.getLastSignedInAccount(this);
updateUI(account);

如果返回非null的A3LSignInAccount对象,则表示用户已经登录应用,您无需再次提示。可以让用户继续进入应用的登录后体验。

如果收到null,则表示用户未登录应用。请提供登录按钮,以便用户可以登录应用。

private void updateUI(A3LSignInAccount account) {
    if (account!=null) {
        // 为用户提供登录后体验
    } else {
        // 提供登录按钮和其他信息,以便用户可以登录应用
    }
}

在应用中添加登录按钮

您可以为应用创建自定义登录按钮,但如果想要使用Google提供的默认登录按钮,请按照下列步骤操作。

  1. 在应用布局中添加登录按钮。

     <com.google.android.gms.common.SignInButton 
     android:id="@+id/sign_in_button" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" />
    
  2. 在Android活动中,为按钮添加OnClickListener。例如,可以在onCreate()方法中添加以下代码。

     findViewById(R.id.sign_in_button).setOnClickListener(this);
    

    用户点击此按钮后,应用会启动登录流程,如下一节所述。

处理登录

通过以下步骤让用户登录。

  1. 在活动的onClick()方法中,处理用户按登录按钮后的情况。

     @Override
     public void onClick(View v) {
         switch (v.getId()) {
             case R.id.sign_in_button:
                 signIn();
                 break;
             // ...
         }
     }
    

    signIn()方法中,使用getSignInIntent()方法创建登录意图。使用startActivityForResult()方法启动该意图,如下所示。

     private void signIn() {
         Intent signInIntent = mA3LSignInClient.getSignInIntent();
         startActivityForResult(signInIntent, RC_SIGN_IN);
     }
    

    启动意图时会有不同的行为,具体取决于运行应用的设备。对于支持Google Play服务的Android设备,系统会在应用内提示用户选择要用于登录的账户。对于没有Google Play服务的设备,应用会打开自定义选项卡并将用户重定向到Google的身份验证网页。

    在这两种情况下,系统都会提示用户选择要用于登录的Google账户,或者输入他们想要用于登录的电子邮件地址。

  2. onActivityResult()方法中,使用A3LSignIn.getSignedInAccountFromIntent()方法来获取任务,该任务成功后会返回A3LSignInAccount对象,如下所示。

     @Override
     public void onActivityResult(int requestCode, int resultCode, Intent data) {
         super.onActivityResult(requestCode, resultCode, data);
    
         // 启动意图后从A3LSignInClient.getSignInIntent(...);返回的结果
         if (requestCode == RC_SIGN_IN) {
             Task<A3LSignInAccount> task = A3LSignIn.getSignedInAccountFromIntent(data);
             handleSignInResult(task);
         }
     }
    

    handleSignInResult()方法的实现如下。生成的A3LSignInAccount对象包含登录用户的信息,例如其姓名。

     private void handleSignInResult(Task<A3LSignInAccount> completedTask) {
         completedTask.addOnCompleteListener(new OnCompleteListener<A3LSignInAccount>() {
             @Override
             public void onComplete(@NonNull Task<A3LSignInAccount> task) {
                 try {
                     A3LSignInAccount account = task.getResult();
                     updateUI(account);
                 } catch (Exception e) {
                     Log.e(TAG, "signInResult:failed code=" + e.getMessage());
                     updateUI(null);
                 }
             }
         });
     }
    

    要访问A3LSignInAccount对象中的用户数据,请使用以下方法:

    • getEmail()用于获取用户的电子邮件地址
    • getId()用于获取用户的Google ID以供客户端使用
    • getIdToken()用于为用户获取ID令牌

    要将当前登录的用户传递到您的后端服务器,请将ID令牌发送到后端服务器,并在该服务器上验证令牌。

访问用户个人资料信息

配置A3LSignIn和A3LSignInClient对象A3LSignInOptions对象的配置方式决定了您可以访问已登录用户的哪些信息。如果使用DEFAULT_SIGN_IN参数或requestProfile()方法配置了A3LSignInOptions,则可以在用户登录后访问其基本个人资料信息。如果使用requestEmail()方法配置了A3LSignInOptions,您也可以访问用户的电子邮件地址。

要请求获取当前登录用户的个人资料信息,请使用A3LSignIn.getLastSignedInAccount()方法,如以下示例所示。

A3LSignInAccount acct = A3LSignIn.getLastSignedInAccount(getActivity());
if (acct != null) {
  String personName = acct.getDisplayName();
  String personGivenName = acct.getGivenName();
  String personFamilyName = acct.getFamilyName();
  String personEmail = acct.getEmail();
  String personId = acct.getId();
  Uri personPhoto = acct.getPhotoUrl();
}

要查看您可以从A3LSignInAccount对象访问所有可能的字段,请参阅A3L身份验证API参考

让用户退出登录

通过添加退出登录按钮,为用户提供退出应用的方式。创建退出登录按钮后,将OnClickListener附加到该按钮,然后配置onClick()方法以调用signOut()方法,如以下代码所示。

@Override
public void onClick(View v) {
    switch (v.getId()) {
        // ...
        case R.id.button_sign_out:
            signOut();
            break;
        // ...
    }
}

private void signOut() {
    mA3LSignInClient.signOut()
            .addOnCompleteListener(this, new OnCompleteListener<Void>() {
                @Override
                public void onComplete(@NonNull Task<Void> task) {
                    // ...
                }
            });
}

应用运行此代码后,用户的Google账户将会从应用退出登录。用户可以选择使用自己的Google账户再次登录,无需任何权限提示(例如请求指定作用域的访问权限)。

断开账户连接

让用户能够断开其Google账户与应用的连接。如果用户选择断开其账户与应用的连接,则您必须删除应用从Google的API获得的信息。如果您撤销访问权限,则此操作会移除用户授予应用通过作用域访问其数据的权限。

要断开用户账户的连接,请调用revokeAccess()方法,如以下示例所示。

private void revokeAccess() {
    mA3LSignInClient.revokeAccess()
            .addOnCompleteListener(this, new OnCompleteListener<Void>() {
                @Override
                public void onComplete(@NonNull Task<Void> task) {
                    // ...
                }
            });
}

OnCompleteListener中,应用可以响应该事件并运行任何其他必需的代码。

撤销访问权限功能的差异

A3L身份验证中提供了撤销对应用访问权限的功能,但该功能与Google的撤销访问权限功能不同。使用Google Sign-In撤销访问权限时,将从用户的Google账户中移除应用。在A3L身份验证中,情况并非如此。在A3L身份验证中,撤销访问权限功能会撤销用户对应用的访问权限,并移除应用获得的数据访问权限,但不会删除用户账户中的条目。要从条目中移除应用,请按照有关撤销方法的Google开发者文档进行操作。

使用后端服务器进行身份验证

如果您使用的是A3L身份验证,并且您的应用会与后端服务器通信,则可能需要识别服务器上当前登录的用户。要安全地识别当前登录的用户,请使用HTTPS将用户的ID令牌发送至您的服务器。在服务器上,验证ID令牌的完整性。使用令牌中的用户数据与已知用户建立会话,或者为新用户创建新的账户记录。

获取ID令牌

首先,必须在用户登录时获取其ID令牌。使用requestIdToken()方法配置A3L身份验证,并将服务器的Web客户端ID传递给此方法,如下所示。

// 仅请求用户的ID令牌,该令牌可用于安全地识别
// 访问后端的用户。这将包含用户的基本
// 个人资料(姓名、头像URL等),因此您应该不需要
// 再次调用,即可提供个性化的应用体验。
A3LSignInOptions a3LSignInOptions = new A3LSignInOptions.Builder(A3LSignInOptions.DEFAULT_SIGN_IN)
        .requestIdToken(getString(R.string.server_client_id))
        .requestEmail()
        .build();

当用户登录时,从登录意图的活动结果获取A3LSignInAccount对象:

Task<A3LSignInAccount> task = A3LSignIn.getSignedInAccountFromIntent(data);
handleSignInResult(task);

用户登录后,从A3LSignInAccount对象获取ID令牌,如下所示。

private void handleSignInResult(@NonNull Task<A3LSignInAccount> completedTask) {
    completedTask.addOnCompleteListener(new OnCompleteListener<A3LSignInAccount>() {
        @Override
        public void onComplete(@NonNull Task<A3LSignInAccount> task) {
            try {
                A3LSignInAccount account = task.getResult();
                String idToken = account.getIdToken();
                // 处理ID令牌
            } catch (Exception e) {
                Log.w(TAG, "signInResult:failed code=" + e.getMessage());
                updateUI(null);
            }
        }
    });
}

将ID令牌发送至您的服务器

使用HTTPS POST请求将ID令牌发送到您的服务器,如下所示。

HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost("https://yourbackend.example.com/tokensignin");

try {
  List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
  nameValuePairs.add(new BasicNameValuePair("idToken", idToken));
  httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

  HttpResponse response = httpClient.execute(httpPost);
  int statusCode = response.getStatusLine().getStatusCode();
  final String responseBody = EntityUtils.toString(response.getEntity());
  Log.i(TAG, "Signed in as: " + responseBody);
} catch (ClientProtocolException e) {
  Log.e(TAG, "将ID发送至后端时出错。", e);
} catch (IOException e) {
  Log.e(TAG, "Error sending ID token to backend.", e);
}

获取ID令牌后,按照Google开发者文档验证ID令牌的完整性中的说明对其进行验证。


Last updated: 2023年12月5日