集成A3L身份验证SDK
请按照本指南将您的应用与A3L身份验证SDK集成。
设置A3L身份验证登录
要将A3L身份验证集成到您的Android应用中,必须配置A3L身份验证并添加启动登录流程的按钮。
初始化A3L身份验证
在登录活动的onCreate()
方法中,初始化A3L身份验证,提供从Google API控制台获得的Android客户端ID,如以下代码所示。
<PREFIX>
是客户端ID中.apps.googleusercontent.com
之前的部分。当您从Google API控制台复制该ID时,请移除.apps.googleusercontent.com
。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对象
接下来,按照以下步骤配置A3LSignIn
和A3LSignInClient
对象。
-
在
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();
-
在
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提供的默认登录按钮,请按照下列步骤操作。
-
在应用布局中添加登录按钮。
<com.google.android.gms.common.SignInButton android:id="@+id/sign_in_button" android:layout_width="wrap_content" android:layout_height="wrap_content" />
-
在Android活动中,为按钮添加
OnClickListener
。例如,可以在onCreate()
方法中添加以下代码。findViewById(R.id.sign_in_button).setOnClickListener(this);
用户点击此按钮后,应用会启动登录流程,如下一节所述。
处理登录
通过以下步骤让用户登录。
-
在活动的
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账户,或者输入他们想要用于登录的电子邮件地址。
-
在
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日