向用于 App Engine 标准环境的 Java 应用对用户进行身份验证

Java Bookshelf 教程的这一部分介绍了如何为拥有 Google 帐号的用户创建登录流程,以及如何使用个人资料信息为用户提供个性化功能。

本教程由多个页面组成,本页面是其中之一。要从头开始阅读并查看设置说明,请参阅 Java Bookshelf 应用

在本地机器上运行应用

要在本地运行应用,请执行以下操作:

  1. getting-started-java/bookshelf-standard/4-auth 目录中,输入以下命令以启动本地网络服务器:

    mvn package appengine:run -Dbookshelf.bucket=[YOUR-BUCKET]
    [YOUR-BUCKET] 替换为您的存储分区名称。
  2. 在网络浏览器中,转到 http://localhost:8080

现在,您可以浏览应用的网页、使用您的 Google 帐号登录、添加图书,并通过顶部导航栏中的我的图书链接查看已添加的图书。

将应用部署到 App Engine 标准环境

要部署到 App Engine 标准环境,请执行以下操作:

  1. 要创建将上传到书架应用的数据存储区索引,请至少创建一本图书,然后点击我的图书。请注意,使用 clean 命令构建应用会删除该本地索引,因此请在要部署的应用构建中执行此操作。
  2. getting-started-java/bookshelf-standard/4-auth 目录中,输入以下命令以部署应用:
  3. mvn appengine:deploy -Dappengine.appId=[YOUR-PROJECT-ID] -Dappengine.version=[YOUR-VERSION] -Dbookshelf.bucket=[YOUR-BUCKET].appspot.com
    将 [YOUR-PROJECT-ID] 替换为您的项目 ID,并将 [YOUR-VERSION] 替换为您的版本(例如 12)或您想要使用的其他某个字符串值。
  4. 在网络浏览器中,输入以下网址:

    https://PROJECT_ID.REGION_ID.r.appspot.com

    替换以下内容:

更新应用后,您可以通过以下方式重新部署更新后的版本:输入您在首次部署应用时使用的命令,并指定相同的项目 ID 和版本。这将覆盖当前部署的应用。如果您在更新的命令行中指定了不同的版本字符串,则新部署将为您的应用创建一个新版本,并将其晋升为当前服务版本。

您可以将应用的非服务版本删除,以减少费用。

要删除应用版本,请执行以下操作:

  1. 在 Cloud Console 中,转到 App Engine 的版本页面。

    转到“版本”页面

  2. 选中要删除的非默认应用对应的复选框。
  3. 点击删除 以删除应用版本。

如需全面了解如何清理可计费资源,请参阅本教程最后一步中的清理部分。

应用结构

下图展示了应用的各个组成部分以及它们如何彼此关联。

身份验证示例结构

了解代码

此部分介绍了应用代码及其工作原理。

当用户点击登录时,LoginServlet 会执行以下操作:

  1. 确定用户目前是否已登录 Google 帐号,如果已登录,则在当前会话中保存用户的电子邮件地址和 ID 信息。

  2. 如果用户没有登录 Google 帐号,则将用户重定向到 Google 帐号登录页面。请注意,App Engine 用户服务会为您处理用户登录过程中的大部分复杂事务。

@SuppressWarnings("serial")
public class LoginServlet extends HttpServlet {
  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp)
      throws IOException, ServletException {

    UserService userService = UserServiceFactory.getUserService();
    if (userService.isUserLoggedIn()) {
      // Save the relevant profile info and store it in the session.
      User user = userService.getCurrentUser();
      req.getSession().setAttribute("userEmail", user.getEmail());
      req.getSession().setAttribute("userId", user.getUserId());

      String destination = (String) req.getSession().getAttribute("loginDestination");
      if (destination == null) {
        destination = "/books";
      }

      resp.sendRedirect(destination);
    } else {
      resp.sendRedirect(userService.createLoginURL("/login"));
    }
  }
}

LogoutServlet 会删除 session 并创建一个新会话:

@SuppressWarnings("serial")
public class LogoutServlet extends HttpServlet {

  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp)
      throws IOException, ServletException {
    // you can also make an authenticated request to logout, but here we choose to
    // simply delete the session variables for simplicity
    HttpSession session =  req.getSession(false);
    if (session != null) {
      session.invalidate();
    }
    // rebuild session
    req.getSession();
  }
}