在穿戴式设备上进行身份验证

Wear OS 应用可以独立运行,无需配套应用。这意味着 Wear OS 应用在访问时需要自行管理身份验证 来自互联网的数据但手表的屏幕尺寸较小 输入功能会限制 Wear OS 应用可以使用的身份验证选项。

本指南介绍了推荐用于 Wear OS 应用的身份验证方法,以及在这些方法不适用于应用用例时的替代方法。

如需详细了解如何设计良好的登录体验,请参阅登录用户体验指南

访客模式

不要对所有功能都要求进行身份验证,相反,您应尽可能多地提供 而无需用户登录。

用户可能会在没有使用过移动设备的情况下发现并安装您的 Wear 应用 因此用户可能没有账号,也不知道该应用有哪些功能 优惠。确保访客模式功能准确展示应用的功能。

某些设备可能会长时间保持解锁状态

在搭载 Wear OS 5 或更高版本的受支持设备上,系统会检测是否 用户的手腕上佩戴设备。如果用户关闭手腕 将设备从手腕上取下后,系统会保留 设备解锁时间比其他情况更长。

如果您的应用需要更高级别的安全性,例如在显示 可能敏感的数据或隐私数据,请先检查手腕检测功能是否 已启用:

val wristDetectionEnabled =
        isWristDetectionAutoLockingEnabled(applicationContext)

如果此方法的返回值为 false,请提示用户登录 账号,然后再显示针对特定用户的内容。

建议的身份验证方法

使用以下身份验证方法,使独立 Wear OS 应用能够: 获取用户身份验证凭据。

使用数据层传递令牌

手机上的配套应用可以使用穿戴式设备数据层将身份验证数据安全地传输到 Wear OS 应用。可以采用消息或数据项的形式传输凭据。

这种类型的身份验证通常不需要用户执行任何操作。不过,请避免在没有通知用户其正在登录的情况下执行身份验证。您可以使用可关闭的简单屏幕通知用户,向他们显示正在从移动设备传输他们的账号凭据。

重要提示:您的 Wear 应用必须至少提供另外一种身份验证方法,因为此选项仅适用于安装了相应移动应用且与 Android 设备完成配对的手表。对于没有安装相应移动应用或所用 Wear OS 设备已与 iOS 设备配对的用户,您应提供替代的身份验证方法。

使用数据层从移动应用传递令牌,如以下示例所示:

val token = "..." // Auth token to transmit to the wearable device.
val dataClient: DataClient = Wearable.getDataClient(context)
val putDataReq: PutDataRequest = PutDataMapRequest.create("/auth").run {
    dataMap.putString("token", token)
    asPutDataRequest()
}
val putDataTask: Task<DataItem> = dataClient.putDataItem(putDataReq)

在手表应用中监听数据更改事件,如以下示例所示:

val dataClient: DataClient = Wearable.getDataClient(context)
dataClient.addListener{ dataEvents ->
    dataEvents.forEach { event ->
        if (event.type == DataEvent.TYPE_CHANGED) {
            val dataItemPath = event.dataItem.uri.path ?: ""
            if (dataItemPath.startsWith("/auth")) {
                val token = DataMapItem.fromDataItem(event.dataItem).dataMap.getString("token")
                // Display interstitial screen to notify the user they are being signed in.
                // Then, store the token and use it in network requests.
            }
        }
    }
}

如需详细了解如何使用穿戴式设备数据层,请参阅在 Wear OS 上发送和同步数据

使用 OAuth 2.0

Wear OS 支持两个基于 OAuth 2.0 的流程,后面几个部分对这些流程进行了介绍:

  • 采用 PKCE(用于代码交换的证明密钥)的授权代码授权,如 RFC 7636 中所定义
  • 设备授权,如 RFC 8628 中所定义

注意:如需确保您的应用在手表进入氛围模式时不会关闭,请在执行身份验证的 activity 中使用 AmbientModeSupport.attach 启用“始终开启”功能。如需详细了解氛围模式下的最佳实践,请参阅让应用始终显示在 Wear 上

用于代码交换的证明密钥 (PKCE)

如需有效地使用 PKCE,请使用 RemoteAuthClient

如需执行从 Wear OS 应用到 OAuth 提供方的身份验证请求,请创建 OAuthRequest 对象。此对象包含一个网址和一个 CodeChallenge 对象,该网址指向用于获取令牌的 OAuth 端点。以下代码展示了创建身份验证请求的示例:

val request = OAuthRequest.Builder(this.applicationContext)
    .setAuthProviderUrl(Uri.parse("https://...."))
    .setClientId(clientId)
    .setCodeChallenge(codeChallenge)
    .build()

构建身份验证请求后,请使用 sendAuthorizationRequest() 方法将其发送到配套应用:

val client = RemoteAuthClient.create(this)
client.sendAuthorizationRequest(request,
    { command -> command?.run() },
    object : RemoteAuthClient.Callback() {
        override fun onAuthorizationResponse(
            request: OAuthRequest,
            response: OAuthResponse
        ) {
            // Extract the token from the response, store it and use it in network requests.
        }

        override fun onAuthorizationError(errorCode: Int) {
            // Handle error
        }
    }
)

此请求会触发对配套应用的调用,然后,配套应用会在用户手机的网络浏览器中显示授权界面。OAuth 2.0 提供方会验证用户身份,并请求用户同意所请求的权限。系统会将响应发送到自动生成的重定向网址。

授权成功或失败后,OAuth 2.0 服务器会重定向到请求中指定的网址。如果用户批准了访问请求,响应中就会包含授权代码。如果用户未批准请求,响应中会包含错误消息。

响应采用查询字符串的形式,类似于以下示例之一:

  https://wear.googleapis.com/3p_auth/com.your.package.name?code=xyz
  https://wear.googleapis-cn.com/3p_auth/com.your.package.name?code=xyz

这会加载一个引导用户前往配套应用的页面。配套应用会验证响应网址,并使用 onAuthorizationResponse API 将响应传递给第三方手表应用。

然后,手表应用可用授权代码来换取访问令牌。

注意:构建 OAuthRequest 后,您可以通过访问 redirectUrl 找到重定向网址。

设备授权

使用设备授权时,用户需要在另一部设备上打开验证 URI。然后,授权服务器会提示他们批准或拒绝请求。

为了简化此过程,请使用 RemoteActivityHelper 在用户的配对移动设备上打开网页,如以下示例所示:

// Request access from the authorization server and receive Device Authorization Response.
val verificationUri = "..." // Extracted from the Device Authorization Response.
RemoteActivityHelper.startRemoteActivity(
    this,
    Intent(Intent.ACTION_VIEW)
        .addCategory(Intent.CATEGORY_BROWSABLE)
        .setData(Uri.parse(verificationUri)),
    null
)
// Poll the authorization server to find out if the user completed the user authorization
// step on their mobile device.

如果您有 iOS 应用,请使用通用链接在您的应用中拦截此 intent,而不要依赖浏览器向令牌授权。

其他身份验证方法

Wear OS 支持其他登录方法,如以下部分所述。

Google 登录功能

Google 登录功能可让用户使用其现有的 Google 账号登录。它提供了 并且易于提供支持,尤其是您已经实施了 在手持式设备应用中进行浏览

在推荐上述身份验证方法之后,Google Sign-In 是排名第二的首选解决方案,因为它在 iOS 上也运行良好。以下 部分介绍了如何完成基本的 Google 登录功能集成。

前提条件

在 Wear OS 应用中开始集成 Google 登录功能之前,您必须先配置 Google API 控制台项目,并设置您的 Android Studio 项目。如需更多信息 请参阅 开始将 Google 登录功能集成到您的 Android 应用中

如果您在某个应用或网站上使用 Google 登录功能, 与后端服务器进行通信,则还需要另外两个前提条件:

  • 为以下对象创建 OAuth 2.0 Web 应用客户端 ID: 与后端服务器通信此客户端 ID 不同于您的应用的客户端 ID。有关 请参阅 <ph type="x-smartling-placeholder"></ph> 启用服务器端访问
  • 通过发送用户的 ID 令牌,在服务器上安全地识别当前已登录的用户 使用 HTTPS。如需了解如何在后端服务器上对用户进行身份验证,请参阅 <ph type="x-smartling-placeholder"></ph> 使用后端服务器进行身份验证

将 Google 登录功能集成到您的应用中

请查看并实现以下步骤,这些步骤在各部分进行了详细介绍 如需将 Google 登录功能集成到您的 Wear OS 应用中,请按照下列步骤操作:

  1. 配置 Google 登录功能
  2. 添加 Google 登录按钮
  3. 点击登录按钮后启动登录流程 已点按

配置 Google 登录功能并构建 GoogleApiClient 对象

在登录 activity 的 onCreate() 方法中,配置 Google 登录以请求 您的应用所需的用户数据然后,使用以下代码创建一个 GoogleApiClient 对象 Google Sign-In API 和您指定的选项的访问权限。这些步骤 如以下示例中所示:

public class MyNewActivity extends AppCompatActivity {

    private static final int RC_SIGN_IN = 9001;

    private GoogleSignInClient mSignInClient;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        GoogleSignInOptions options =
                new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                        .build();

        mSignInClient = GoogleSignIn.getClient(this, options);
    }
}

在应用中添加 Google 登录按钮

如需添加 Google 登录按钮,请完成以下步骤:

  1. SignInButton 添加到应用的布局中:
  2.  <com.google.android.gms.common.SignInButton
     android:id="@+id/sign_in_button"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content" />
    
  3. 在应用的 onCreate() 方法中,注册按钮的 OnClickListener,让用户在点按后登录:
  4. Kotlin

    findViewById<View>(R.id.sign_in_button).setOnClickListener(this)
    

    Java

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

创建登录 intent 并启动登录流程

处理 onCLick() 中的登录按钮点按操作 方法是使用 <ph type="x-smartling-placeholder"></ph> getSignInIntent() 方法。然后使用 <ph type="x-smartling-placeholder"></ph> startActivityForResult() 方法。

Intent intent = mSignInClient.getSignInIntent();
startActivityForResult(intent, RC_SIGN_IN);

系统会提示用户选择用于登录的 Google 账号。如果您请求了范围 除个人资料、电子邮件和 OpenID 外,系统还会提示用户授予 资源。

最后,在 activity 的 <ph type="x-smartling-placeholder"></ph> onActivityResult 方法,使用以下代码检索登录结果 getSignInResultFromIntent。获取登录结果后,您可以 使用 <ph type="x-smartling-placeholder"></ph> isSuccess 方法。如果登录成功,您可以调用 <ph type="x-smartling-placeholder"></ph> getSignInAccount 方法,用于获取 GoogleSignInAccount 对象,其中包含有关已登录用户的信息 用户,例如用户的姓名。这些步骤如以下示例所示:

Kotlin

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
    super.onActivityResult(requestCode, resultCode, data)

    // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...).
    if (requestCode == RC_SIGN_IN) {
        Auth.GoogleSignInApi.getSignInResultFromIntent(data)?.apply {
            if (isSuccess) {
                // Get account information.
                fullName = signInAccount?.displayName
                mGivenName = signInAccount?.givenName
                mFamilyName = signInAccount?.familyName
                mEmail = signInAccount?.email
            }
        }
    }
}

Java

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...).
    if (requestCode == RC_SIGN_IN) {
        GoogleSignInResult signInResult = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
        if (signInResult.isSuccess()) {
            GoogleSignInAccount acct = signInResult.getSignInAccount();

            // Get account information.
            fullName = acct.getDisplayName();
            givenName = acct.getGivenName();
            familyName = acct.getFamilyName();
            email = acct.getEmail();
        }
    }
}

如需查看实现 Google 登录的示例应用,请参阅 <ph type="x-smartling-placeholder"></ph> GitHub 上的 Horologist Google Sign-In 示例

自定义代码身份验证

作为前面描述的身份验证方法的替代方法, 可能会要求用户通过其他设备进行身份验证 (例如手机或平板电脑),并获取一个短时效的数字代码。然后,用户进入 确认其身份,并接收身份验证令牌。

此身份验证流程使用应用的登录模块,或者 会将第三方身份验证提供程序的登录方法手动集成到您的应用代码中。 尽管这种身份验证方法需要手动操作和额外工作, 更安全,如果您需要在独立 Wear OS 应用中更早地进行身份验证,可以使用此方法。

此设置的身份验证流程工作方式如下:

  1. 用户使用 Wear OS 应用执行一项需要授权的操作。
  2. Wear OS 应用向用户显示身份验证屏幕并指示 用户从指定网址输入代码。
  3. 用户切换到移动设备、平板电脑或 PC,然后启动浏览器, 导航到 Wear OS 应用中指定的网址并登录。
  4. 用户收到一个短时效数字代码,请将其输入到 Wear OS 应用中 在 Wear OS 中使用板载键盘进行身份验证屏幕:

  5. 从此时开始,您可以使用输入的代码作为证据来证明这是正确的 用户使用相应代码换取 Wear OS 设备上存储并保护的身份验证令牌 进行身份验证的调用

注意:用户生成的代码必须是纯数字,不得包含任何字母字符。

此身份验证流程如下图所示: