Google Cloud Platform:用户管理





0/5 (0投票)
Google Cloud Platform - 第 3 部分:管理
- Google Cloud Platform:Google App Engine 入门(第一部分)
- Google Cloud Platform:使用 Google App Engine 进行部署(第二部分)
- Google Cloud Platform:用户管理(第三部分)
- Google Cloud Platform:移动端点(第四部分)
- Google Cloud Platform - Google Cloud SQL(第五部分)
- Google Cloud Platform - Google Cloud Datastore(第六部分)
- Google Cloud Platform - Google Cloud Storage(第七部分)
第三部分:用户管理
上次我们说到,我们的英雄……呃,我是说,英勇的应用,它正愉快地运行在云端,向所有路过的人打招呼,甚至可能直呼其名,如果他们恰好提供了姓名的话。
这就引出了一个有趣的问题:用户身份。许多(如果不是大多数)互联网应用程序都需要以某种独特的方式识别浏览器背后的用户,原因多种多样。有时应用程序需要显示用户的个人信息,并且不应向除该特定用户之外的任何人显示;有时应用程序在允许用户使用其任何部分之前需要验证用户的身份;有时应用程序只是想为用户提供更个性化的体验。无论出于何种原因,用户身份管理通常都是 Web 应用程序“必备”功能列表的顶部附近。
那么,如果你和许多开发者一样,接下来的讨论将围绕一系列围绕此概念的功能展开:用于验证人类用户的 CAPTCHA、登录屏幕、密码强度规则、用户名唯一性验证、我忘记密码了屏幕和验证、电子邮件验证、加盐和加密的密码,以及像 OAuth 或 OpenID(或两者)这样的联合安全系统。
或者,你只需让 Google 来担心这些。
用户管理
在 Google Cloud Platform 上运行的一个主要优势是,Google 构建了大量的(顺便说一句,这是一种实际的计量单位)库和 API 来支持它,所有这些都可以从你在 Google Cloud Platform 上运行的基于 Java 的应用程序中轻松利用。在这种特定情况下,我们可以利用 Google 身份验证和用户管理系统(你用来访问 Gmail 的系统,以及如果你遵循上一篇文章的指示,在 Google App Engine 中创建应用项目时使用的系统)来识别用户。你无需构建登录屏幕、电子邮件验证等等,只需导入正确的 API,调用正确的方法,然后让 Google 完成繁重的工作。
流程
根据业务需求,用户与应用程序的交互方式有几种不同的思考方式。一种常见于许多内部和外部应用程序的方法是,用户在成功登录之前无法访问应用程序的任何方面——换句话说,对于任何未经授权使用该应用程序的人来说,该应用程序完全是不透明的。该方法的轻微变体(对于大多数外部、面向消费者的应用程序都很常见)是允许人们申请加入这个专属俱乐部的成员资格,但除此之外,应用程序的行为方式相同:未经成功登录,无法访问应用程序的任何方面。
其他应用程序则倾向于不那么二元地区分授权,可能允许任何人使用应用程序的某些部分,同时为拥有已识别凭证集的用户保留某些功能和/或权益。(大多数电子商务系统通常属于此类:你可以随意浏览,但只有当你成为我们网站的注册会员时,才能享受免费送货,这样我们就可以向你发送垃圾邮件并将你的电子邮件卖给出价最高者。)
从 Google App Engine 开发者的角度来看,这种区别并不重要,只是要知道在哪里向用户索要凭证以及在用户未提供可接受的凭证时应采取哪些措施。例如,一个想要遵循“全进全出”的二元模型的应用程序,可能会选择设置一个 servlet 过滤器来检查当前会话中已建立的登录凭证,并在没有凭证的情况下将用户重定向到一个解释为什么会被重定向的页面。然而,我的应用程序不想那么苛刻——它仍然想要热情友好等等,所以我将要求提供 Google 凭证,但仍然向那些不是 Google 可识别用户的用户提供问候。只是可能没那么个性化。
包,包
用户管理 API 位于 com.google.appengine.api.users 包中,因此首要任务是将其导入 servlet。
import com.google.appengine.api.users.*;
然后,就像许多 Java API 一样,我们需要一个对象引用,该对象充当其余 API 的网关,在 Google 用户服务的情况下,这是一个 UserService
对象,通过调用静态 UserServiceFactory.getUserService()
方法获得。这个 UserService
对象,以及它将为我们获取的 User 对象(稍后详细介绍),构成了开发者使用的绝大部分接口。事实上,与它提供的所有功能相比,API 的实际大小非常小,这一点更值得注意。
让我们从基础开始。
你是谁?
UserService
对象返回已认证用户的主要方法是 getCurrentUser()
方法,该方法返回(不出所料)一个 User 对象,其中包含已认证用户的凭证信息(稍后详细介绍),否则返回 null,表示没有此类用户已登录。因此,原则上,检查用户是否已通过 Web 应用程序进行身份验证是一个单一的方法调用,检查 null 结果即可。
public class HelloServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { UserService userService = UserServiceFactory.getUserService(); User user = userService.getCurrentUser(); if (user != null) { PrintWriter out = response.getWriter(); out.println("<html>"); out.println("<body>"); out.println("<p>Hello, " + user.getNickname() + "</p>"); out.println("</body>"); out.println("</html>"); } else { // . . . } } }
User 对象上有许多方法可以描述 Google 对该用户的了解:他们的电子邮件地址 (getEmail
)、他们的人类标识符 (getNickname
,可能是他们的“昵称”、电子邮件地址或别的东西,但通常是他们自己选择的内容)、他们的 Google 标识符 (getUserId
),以及一些在特定情况下可能很有用的其他信息,例如用于验证此用户的域(身份验证系统)(getAuthDomain
) 或用户的联合身份 (getFederatedIdentity
),这可能只在 Google 身份验证与 OAuth 或 OpenID 等系统结合使用的情况下才有用。
在用户不是已通过 Google 登录的用户的情况下,我们需要创建一个 URL,他们可以重定向到该 URL,以便捕获他们的凭证(用户名和密码)。这就是 UserService
发挥其另一半功能的地方,通过与 Google 的身份验证系统一起生成一个 URL,该 URL 将捕获用户的信息并将其重定向回我们。
else { String host = request.getProtocol() + "://" + request.getServerName() + (request.getServerPort() != 80 ? request.getServerPort() : ""); String loginUrl = userService.createLoginURL(host + "/hello"); PrintWriter out = response.getWriter(); out.println("<html>"); out.println("<body>"); out.println("<p>Please <a href='" + loginUrl + "'>log in</a> " + + "for a nice, friendly greeting!"); out.println("</body>"); out.println("</html>"); }
请注意,createLoginUrl
方法接受一个字符串参数,即用户成功身份验证后应重定向到的页面。在这个极其简化的应用程序中,就是我们原来的页面,但在其他应用程序中,这通常是应用程序的主页,充满了菜单选择的优点。
请注意,如果此端点是 JSON 传递的数据端点(例如移动应用程序将使用的端点),那么 createURL 方法将没有太大用处;相反,servlet 可能会返回一个 400 类错误代码(可能是 401),表示 servlet 在未经验证的情况下无法返回数据,然后移动应用程序将不得不呈现一个本地登录屏幕来收集这些凭证。当我们在后续文章中介绍 Google 移动端点 API(一套专门用于构建此类端点的 API)时,会有更多关于这方面的内容。
角色扮演游戏
尽管我个人不喜欢将面向用户的应用程序和面向管理员的应用程序混合到同一个 Web 应用程序中(因为这会增加意外信息泄露的可能性),但许多系统希望区分“普通”用户和“管理员”用户,以便显示不同的链接、页面或信息。User 对象不支持完整的基于角色的安全系统,但它允许通过 User 对象上的 isAdmin()
方法调用来区分“管理员”和“非管理员”用户。(被识别为“管理员”用户的用户是在管理员控制台中应用程序项目页面中被授予该状态的用户。)
测试,测试,测试
重要的是要注意,此应用程序现在依赖于 Google 服务和 Internet,因为如果 Google 服务中断,或者更常见的是,你的 Internet 连接中断或不稳定,此应用程序将永远无法处理身份验证请求。诚然,如果 Internet 连接中断,你在生产环境中也无法做其他很多事情,但在测试期间,许多开发人员处于离线状态,或者更重要的是,不想一直输入用户名/密码组合。
正是出于这个原因,Google 将 UserService 定义为一个接口,以便任何称职的依赖注入容器或 API 都可以注入一个返回已知常量的模拟 UserService
对象,从而实现完全自动化的测试。
但我的老板不喜欢 Google……
不幸的是,这是开发者生活中一个事实,许多优雅的解决方案都无法实施,因为老板(或客户、政府,或者“客户端”讨论中的任何其他人)对使用所述优雅解决方案有某种问题。我们可以抱怨、嘟囔并发表“愚蠢的用户”之类的评论,但事实仍然是,他们付钱,他们可以做这些决定。(而且老实说,第三方持有用户身份验证数据的法律和责任影响仍然有些不确定,对于某些企业来说,这风险太大了。)
或者,也许你的用户目前正在使用 Google 之外的其他系统进行身份验证,并且尝试将他们从当前系统大规模迁移到 Google 系统的想法足以让你的系统管理员头晕几下。或者,也许你的用户实际上并不是任何单一系统的一部分,或者实际上是消费者,而你想让他们使用 Facebook、Twitter、LinkedIn 或……。
幸运的是,Google 拥有一个 OAuth 用户提供程序,它的工作方式几乎与我们上面展示的 UserService 方法相同。OAuthServiceFactory 使用静态 getOAuthService()
方法返回 OAuthService
对象的实例,该对象可以用来检查当前用户的 OAuth 凭证,以我们上面 UserService API 的 User 对象形式。它提供了一个非常即插即用的替代方案。(请注意,开发者仍然需要设置一个链接到将执行身份验证的 OAuth 提供程序,如 OAuth 提供程序的文档所述。因此,例如,如果应用程序希望 Facebook 进行身份验证,则开发者必须根据 Facebook 的文档将用户重定向到 Facebook OAuth 端点,并设置一个重定向回此应用程序。这都是标准的 OAuth 内容,可以从任何 OAuth 教程中获得,并且超出了本次讨论的范围。)
一个人同时使用这两种身份验证系统不太可能,因为那样会有两个完全独立的“主用户列表”,但我敢肯定,我一这么说,就会有人有一个正当的理由这样做,所以如果你同时使用两者,请小心。
摘要
Google Cloud Platform 提供了许多 API,可以减少开发者创建“生产就绪”应用程序所需执行的总工作量。上面描述的用户服务和 OAuth 服务只是冰山一角;完整的 Javadoc 可在 https://developers.google.com/appengine/docs/java/javadoc/ 找到。
在下一篇文章中,我们将探讨几乎所有应用程序都必须做的下一件事——存储数据——以及 Google Cloud Platform 为此提供的各种机制。但现在,编码愉快!