本帖最后由 truthrudy 于 2016-3-14 14:17 编辑
英文原文:Using Google Sign-In with your server 发布人:开发顾问 Laurence Moroney
这是有关在 Android 上使用 Google Sign-In 以及如何在 Android 应用中充分利用世界级安全保障系列博文的第三部分。在第 1 部分中,我们谈论的主题是可供您做出的用户体验改进。在第 2 部分中,我们深入了解了那些令代码编写工作得到极大简化的 Google Sign-In API 客户端变更。
在这篇博文中,我们将展示如何将 Google Sign-In 用于后端。这样一来,登录设备的用户便可通过安全的身份验证访问其位于后端服务器上的数据。
在您的服务器上使用凭据首先,让我们看一看用户登录您的应用后会发生什么情况,但他们同样需要进行身份验证,才能访问您的后端服务器。想像以下情境:您开发了一款为用户上门送餐的应用。用户登录您的应用后,应用将获得其身份。您将用户地址和订餐偏好存储在您服务器上的一个数据库中。
除非您的服务器端点受到某种身份验证机制的保护,否则攻击者只需猜中用户的电子邮件地址,便可向您的用户数据库执行读写操作。 图 1.第三方可能利用虚假电子邮件对您的服务器实施欺诈
这并非仅仅造成糟糕的用户体验,更会招致客户数据被盗和滥用风险。您可以通过在用户登录应用时从 Google 获取一个令牌,然后将该令牌传递至您的服务器来防止发生这种情况。您的服务器随即验证该令牌的确是由 Google 发放给所需用户,并且专用于您的应用(根据您的适用对象设置,见下文)。此时,您的服务器即可确信调用者的确是您的用户,而不是穷凶极恶的攻击者。然后,服务器便可提供所需详情作为响应。 图 2.第三方虚假令牌将遭拒
让我们了解一下实现此目的的步骤: 第 1 步: 您的 Android 应用在登录 Google 后获取一个 ID 令牌 (*)。此处提供的示例对此做了清楚的展示。为此,将在创建 GoogleSignInOptions 对象时调用 requestIdToken 方法。 这要求您获取服务器的客户 ID。此处提供了有关如何获取该 ID 的详情(见第 4 步)。
您的 Android 应用获得令牌后,便可 通过 HTTPS 将 其 POST 至您的服务器,后者随即尝试对其进行验证。
(*) 按照 RFC7519 的定义,ID 令牌是 JSON Web 令牌。它们是开放的行业标准方法,用于以安全方式表示双方之间的声明。
第 2 步: 您的服务器收到来自 Android 客户端的令牌。它应该随即利用 Google API 客户端内容库中提供的方法验证令牌,具体地讲,便是确认令牌由 Google 发放,并且预期适用对象是您的服务器。 您的服务器可以利用 GoogleIdTokenVerifier 类来验证令牌,然后提取所需身份数据。应该使用“sub”字段(getSubject() 方法提供)提供的稳定字符串标识符来标识或有电子邮件地址变更的用户,并将变更内容键入数据库。还提供了其他 ID 令牌字段,包括姓名、电子邮件地址和照片 URL。以下这个示例 servlet 在 Google App Engine 上进行了测试,可使用提供的内容库验证令牌。您可以利用这些内容库在本地验证令牌,无需进行网络调用。
GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(transport, jsonFactory) // Here is where the audience is set -- checking that it really is your server // based on your Server’s Client ID .setAudience(Arrays.asList(ENTER_YOUR_SERVER_CLIENT_ID_HERE)) // Here is where we verify that Google issued the token .setIssuer("https://accounts.google.com").build(); GoogleIdToken idToken = verifier.verify(idTokenString); if (idToken != null) { Payload payload = idToken.getPayload(); String userId = payload.getSubject(); // You can also access the following properties of the payload in order // for other attributes of the user. Note that these fields are only // available if the user has granted the 'profile' and 'email' OAuth // scopes when requested. (e.g. you configure GoogleSignInOptions like // the sample code above and got a successful GoogleSignInResult) // Note that some fields may still be null. String email = payload.getEmail(); boolean emailVerified = Boolean.valueOf(payload.getEmailVerified()); String name = (String) payload.get("name"); String pictureUrl = (String) payload.get("picture"); String locale = (String) payload.get("locale"); String familyName = (String) payload.get("family_name"); String givenName = (String) payload.get("given_name");
请注意,如果您的现有应用使用 GoogleAuthUtil 来获取用于传递至后端的令牌,则您应该切换到上述最新 ID 令牌验证内容库和机制。我们将在日后发布的博文中介绍推荐的服务器端最佳做法。 这篇博文展示如何利用身份验证技术来确保您的用户符合其声明的身份。在下一篇博文中,我们将介绍如何利用 Google Sign-In API 进行授权,以便用户实现某种目的,例如:在您的应用和后端服务内访问 Google Drive 等 Google 服务。
您可以在 Google Identity Platform 开发者网站上了解更多有关 Google 身份验证技术的信息。
|