适用于基于HarmonyOS的移动端应用,且希望基于OAuth 2.0协议标准接入华为帐号的场景。
Authorization Code模式基于OAuth 2.0协议标准,应用可以通过获取帐号用户的临时授权票据(Authorization Code),使用户通过帐号安全登录您的应用,首次登录时,要求用户同意授权,当身份验证信息到期时,只需要从服务器端通过刷新令牌刷新访问令牌,从而更快,更可靠,更方便。Authorization Code模式仅适用于有自己服务器的应用。
完整的Authorization Code授权登录流程为:
| 设备类型 | OS版本 | HMS Core(APK)版本 |
|---|---|---|
| 手机、平板 | HarmonyOS 2.0及以上 | 5.0.0.300及以上 |
| 车机 | HarmonyOS 2.0及以上 | 6.2.0.300及以上 |
| 华为智慧屏、智能手表(wearable,不支持运动手表liteWearable) | HarmonyOS 2.0及以上 | 6.5.0.300及以上 |
HarmonyOS(Java)必须在单HAP包场景下使用,暂不支持多HAP包场景。
在使用华为帐号SDK之前,要求应用先通过调用AccountAuthManager.init(AbilityPackage abilityPackage)方法,完成华为帐号SDK的初始化。
建议在应用初始化的时候就完成华为帐号SDK的初始化,如下。
“Java” // 示例:在应用初始化时就完成华为帐号SDK的初始化 public class MyApplication extends AbilityPackage { @Override public void onInitialize() { super.onInitialize(); // 调用示例initHuaweiAccountSDK方法,在HarmonyOS应用初始化方法onInitialize中进行华为帐号SDK初始化 initHuaweiAccountSDK(); } @Override public void onEnd() { super.onEnd(); } // 示例:此方法中调用华为帐号SDK的初始化方法AccountAuthManager.init()进行初始化 private void initHuaweiAccountSDK() { Task<Void> task; try { // 调用AccountAuthManager.init方法初始化 task = AccountAuthManager.init(this); } catch (ApiException apiException) { apiException.getStatusCode(); return; } task.addOnSuccessListener(new OnSuccessListener<Void>() { @Override public void onSuccess(Void v) { //初始化成功 } }); task.addOnFailureListener(new OnFailureListener() { @Override public void onFailure(Exception e) { // SDK初始化失败 if (e instanceof ApiException) { ApiException apiException = (ApiException) e; // SDK初始化失败,status code标识了失败的原因,请参见API参考中的错误码了解详细错误原因 apiException.getStatusCode(); } } }); } }
“Java”
Button mBtnHuaweiIdSignIn = (Button) findComponentById(ResourceTable.Id_btn_hwid_sign_in);
mBtnHuaweiIdSignIn.setClickedListener((Component c) -> {
huaweiIdSignIn();
}); 在huaweiIdSignIn方法中,构造登录授权请求参数AccountAuthParams和华为帐号登录授权服务AccountAuthService。
构造AccountAuthParams参数时,调用AccountAuthParamsHelper.setAuthorizationCode()方法设置使用code模式。
调用静默登录接口silentSignIn进行静默登录。
如果静默登录成功,在成功监听中获取华为帐号对象AuthAccount,通过AuthAccount.getAuthorizationCode()获取到授权码Authorization Code;
如果静默登录失败,需要在静默登录的失败监听中调用前台登录授权signIn接口,显式拉起登录授权视图进行登录,如果前台登录授权接口成功,在成功监听中获取华为帐号对象AuthAccount,通过AuthAccount.getAuthorizationCode()获取到授权码Authorization Code。
“Java” private void huaweiIdSignIn() { AccountAuthService accountAuthService; // 1、配置登录请求参数AccountAuthParams,包括请求用户的id(openid、unionid)、email、profile(昵称、头像)等; // 2、DEFAULT_AUTH_REQUEST_PARAM默认包含了id和profile(昵称、头像)的请求; // 3、如需要再获取用户邮箱,需要setEmail(); // 4、通过setAuthorizationCode()来选择使用code模式,最终所有请求的用户信息都可以调服务器的接口获取; AccountAuthParams accountAuthParams = new AccountAuthParamsHelper(AccountAuthParams.DEFAULT_AUTH_REQUEST_PARAM) .setAuthorizationCode() .createParams(); try { accountAuthService = AccountAuthManager.getService(accountAuthParams); } catch (ApiException e) { // 处理初始化登录授权服务失败,status code标识了失败的原因,请参见API参考中的错误码了解详细错误原因 e.getStatusCode(); return; } // 调用静默登录接口。 // 如果华为系统帐号已经登录,并且已经授权,会登录成功; // 否则静默登录失败,需要在失败监听中,显式调用前台登录授权接口,完成登录授权。 Task<AuthAccount> task = accountAuthService.silentSignIn(); // 添加静默登录成功处理监听 task.addOnSuccessListener(new OnSuccessListener<AuthAccount>() { @Override public void onSuccess(AuthAccount authAccount) { // 静默登录成功后,根据结果中获取到的帐号基本信息更新UI } }); // 添加静默登录失败监听 task.addOnFailureListener(new OnFailureListener() { @Override public void onFailure(Exception e) { if (e instanceof ApiException) { // 静默登录失败,显式调用前台登录授权接口,完成登录授权。 Task task = accountAuthService.signIn(); if (task == null) { return; } task.addOnSuccessListener(new OnSuccessListener<AuthAccount>() { @Override public void onSuccess(AuthAccount account) { // 从account中获取授权码code account.getAuthorizationCode(); } }); task.addOnFailureListener(new OnFailureListener() { @Override public void onFailure(Exception e) { if (e instanceof ApiException) { ApiException apiException = (ApiException) e; // 登录失败,status code标识了失败的原因,请参见API参考中的错误码了解详细错误原因 apiException.getStatusCode(); } } }); } } }); }
该部分代码需要您根据应用设计自己开发。
获取到code后调用服务器接口向帐号服务器请求获取Access Token、Refresh Token。接口详细信息请参见获取凭证Access Token,接口调用错误码信息请参见错误码。
如您使用的是Java语言,accountservertool.jar中提供了AuthCodeUtil.getUserInfos(String accessToken,String getNickName)方法供您使用,详细信息请参见accountservertool.jar工具包使用说明。
Access Token过期处理
由于Access Token的有效期(60分钟)较短,当Access Token失效或者即将失效时(可通过NSP_STATUS错误码判断),可以使用Refresh Token(有效期180天)通过获取凭证Access Token接口向帐号服务器请求获取新的Access Token。
RefreshToken过期处理
由于Refresh Token的有效期为180天,当Refresh Token失效(可通过错误码判断)后,应用服务器需要通知客户端,重新调用Account SDK登录授权接口,请求用户重新授权。
帐号退出是指应用向用户提供可以退出当前华为帐号的入口,应用通过signOut接口通知HMS Core SDK清除本地当前已经登录的华为帐号信息。
“Java”
Button mBtnHuaweiIdSignOut = (Button) findComponentById(ResourceTable.Id_btn_signout);
mBtnHuaweiIdSignOut .setClickedListener((Component c) -> {
signOut();
}); “Java” private void signOut() { AccountAuthService accountAuthService = null; AccountAuthParams accountAuthParams = new AccountAuthParamsHelper(AccountAuthParams.DEFAULT_AUTH_REQUEST_PARAM).setEmail().createParams(); try { accountAuthService = AccountAuthManager.getService(accountAuthParams); } catch (ApiException e) { // 处理初始化登录授权服务失败,status code标识了失败的原因,请参见API参考中的错误码了解详细错误原因 e.getStatusCode(); return; } Task<Void> task = accountAuthService.signOut(); task.addOnSuccessListener(new OnSuccessListener<Void>() { @Override public void onSuccess(Void v) { // 华为帐号登出成功,接入应用处理登出后逻辑 } }); task.addOnFailureListener(new OnFailureListener() { @Override public void onFailure(Exception e) { // 华为帐号退出失败 if (e instanceof ApiException) { ApiException apiException = (ApiException) e; // 华为帐号退出失败,status code标识了失败的原因,请参见API参考中的错误码了解详细错误原因 apiException.getStatusCode(); } } }); }
为了提升应用隐私安全,应用可以提供入口,供用户取消对应用的授权。
取消授权接口通过调用AccountAuthService类对象的cancelAuthorization方法,实现取消授权。
“Java”
mBtnCancelAuthorization = (Button) findComponentById(ResourceTable.Id_btn_cancelauthorization);
mBtnCancelAuthorization.setClickedListener((Component c) -> {
cancelAuthorization();
}); “Java” private void cancelAuthorization() { AccountAuthService accountAuthService; AccountAuthParams accountAuthParams = new AccountAuthParamsHelper(AccountAuthParams.DEFAULT_AUTH_REQUEST_PARAM).setEmail().createParams(); try { accountAuthService = AccountAuthManager.getService(accountAuthParams); } catch (ApiException e) { // 处理初始化登录授权服务失败,status code标识了失败的原因,请参见API参考中的错误码了解详细错误原因 e.getStatusCode(); return; } // 调用取消授权接口 Task<Void> task = accountAuthService.cancelAuthorization(); task.addOnSuccessListener(new OnSuccessListener<Void>() { @Override public void onSuccess(Void v) { // 取消授权成功 } }); task.addOnFailureListener(new OnFailureListener() { @Override public void onFailure(Exception e) { // 取消授权失败 if (e instanceof ApiException) { ApiException apiException = (ApiException) e; // 华为帐号取消授权失败,status code标识了失败的原因,请参见API参考中的错误码了解详细错误原因 apiException.getStatusCode(); } } }); }