8

我想要求用户在访问我的GAE(Google App Engine)应用程序的某些部分时使用登录名/密码。我想限制对一组预定义用户的访问,例如在可以将新数据上传到数据存储区的页面上。

我发现 GAE 有 3 种方法可以解决这个问题,但看起来只有最后一种(最复杂的)可以解决我的问题:

  1. 使用部署描述符(<security-constraint>在 web.xml 中)。这不好,因为这些用户可以访问,即使作为 GAE 应用程序管理页面的查看者,他们可以在其中查看计费历史记录、浏览数据存储、日志等,这是我必须避免的事情。

  2. 使用联合登录 ( Open ID ) ( https://developers.google.com/appengine/articles/openid ) 并允许用户使用他们的 Google、Yahoo! 或其他身份登录。这不是一个解决方案,因为我想限制对一小部分用户(最多 5 个)的访问,并且不允许每个人都使用该应用程序。

  3. 另一种选择是创建只能通过 HTTPS 访问的简单自定义登录页面,并让用户在 POST 请求中发送用户名和密码(它可以很简单,因为我们有安全的https连接)到 servlet,在 servlet 上生成一些会话标识符具有指定的有效性,并使其成为每个后续请求的一部分。它还需要在用户每次发送 GET 或 POST 请求时手动检查会话标识符是否存在并且同时没有过期。

关于如何维护管理员帐户的任何其他/更好的建议?可以HttpSession帮助解决最后一个变体吗?

亲切的问候, STeN

4

4 回答 4

2

我建议使用标准的 Google 登录页面。在您的身份验证控制器中使用类似的东西(Java + Jersey 框架,当然不是必需的):

@Path("/login")
public Response login(@Context UriInfo ui) throws Exception {
  UserService userService = UserServiceFactory.getUserService();
  com.google.appengine.api.users.User user = userService.getCurrentUser();
  Response response;
  if (user == null) {
    URI uri = new URI(userService.createLoginURL(ui.getBaseUri().toString()));
    response = Response.seeOther(uri).build();
  } else {
    URI uri = new URI("/");
    response = Response.seeOther(uri).build();
  }
  return response;
}

@GET
@Path("/logout")
public Response logout(@Context UriInfo ui) throws Exception {
  UserService userService = UserServiceFactory.getUserService();
  com.google.appengine.api.users.User user = userService.getCurrentUser();
  Response response;
  if (user == null) {
    URI uri = new URI("/");
    response = Response.seeOther(uri).build();
  } else {
    URI uri = new URI(userService.createLogoutURL(ui.getBaseUri().toString()));
    response = Response.seeOther(uri).build();
  }
  return response;
}

如果用户未登录(基本上未登录),登录方法会将您的应用重定向到 Google 登录页面。注销方法将注销用户。

希望这可以帮助

于 2012-04-11T12:14:27.957 回答
1

一些注意事项:

  1. AFAIK 你的假设是不正确的。登录到应用程序与管理页面权限无关。您需要通过“权限”页面显式添加用户,以便他们可以访问管理页面。

  2. 用户使用 OpenID 登录后,您仍然可以检查用户属性(电子邮件)并拒绝他们访问。

  3. 这当然是可行的。跟踪用户的自然方式是会话。谷歌示例。

在这两种情况下 2.' 3. 建议有一个 servlet 过滤器,如果有用户登录则检查会话,如果用户未登录则拒绝访问(返回 404)。

于 2012-04-11T09:04:41.957 回答
1

我使用 2 和 3 的组合。我允许所有用户登录,但我将操作限制在特定的电子邮件地址。这些可以硬编码或(更好)在数据存储和内存缓存中(这样您就不必在每个请求上查询数据存储)。如果您愿意,您还可以将此数据缓存在 Java 中的静态变量中 - 请注意,如果您更改有权访问的用户,您可能需要手动终止实例。如果像我一样,您很少/从不更改访问权限,那么这应该不是问题。

允许所有用户登录实际上使他们无法访问我的应用程序 - 他们看到管理页面,但除了一条消息说“您无权访问这些管理选项中的任何一个”之外,它们是空的。

于 2012-04-11T08:54:26.473 回答
-1

注意第三种解决方案:我的 webapp 不传递用户名和密码,而是询问用户名和 apiSecret(在第一次登录时自动生成),因此如果出现问题,您可以快速使 apiSecret 无效(并重新生成)。

还有另一种选择:OAuth (https://developers.google.com/appengine/docs/java/oauth/)。这是我的一段代码(UserAccount 是我的代表用户的类;用户是“com.google.appengine.api.users.User”,retrieveUser(..) 是从登录的“用户”中检索我的 UserAccount 的函数):

public UserAccount getUserLogged(HttpServletRequest request) {
    try {
        User loggedUser = oauthService.getCurrentUser();
        if(loggedUser!=null) {
            return super.userAB.retrieveUser(loggedUser);
        }
    } catch (OAuthRequestException e) {
        return null;
    }
    return null;
}
于 2012-04-11T13:02:48.880 回答