GWT应用程序是否受益于会话群集?

时间:2013-05-15 10:51:46

标签: java session gwt session-state cloudbees

许多Java PaaS(例如CloudBees session stores)提供会话群集/存储,使得用户在特定请求上路由到哪个服务器节点无关紧要,所有服务器节点共享相同的存储会话数据,因此任何服务都可以为任何客户端请求提供服务。

我想知道这是如何应用于客户端MVC,单页应用程序,如GWT应用程序。

使用GWT,大多数应用程序都以JavaScript身份执行客户端。通常,客户端访问服务器的唯一时间(通过GWT-RPC或RequestFactory)是客户端需要数据的时候,在这种情况下,它会在GWTServlet之下进行特殊调用。

我对共享会话存储的理解适用于HttpServlet以及客户端(请求)和服务器(响应)之间的来回对话。但这似乎并不适用于GWT-land。

所以我问:我的GWT应用程序可以从上面提到的应用程序会话存储中受益吗? 为什么或为什么不呢?如果是这样,具体的例子非常赞赏!提前谢谢!

示例:

我有一个允许客户端用户执行某些操作的应用程序:

public class BackOfficeServlet extends HttpServlet {
    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response) {
        User u = getUserFromRequest(request);
        Action a = getActionFromRequest(request);

        // If the user is allowed to do the action, then do it.
        if(UserActionAuthenticator.actionIsAllowed(u, a))
            a.execute(u, request);
    }
}

HttpSession如何/在何处用于添加上述代码示例中不存在的安全性或功能?

1 个答案:

答案 0 :(得分:1)

仅当您使用会话存储某些数据时,才使用会话群集。问你:你需要在服务器端会话中保存一些东西吗?如果响应为否,则也不需要使用会话群集。 GWT完全是关于有状态的客户端。大多数时候,您可以通过直接在浏览器中保存会话数据来消除对服务器端会话的需求。我举一个例子,我不想这样做(在这种情况下,会话聚类会很有用):

想象一下,您的应用是一个后台。每个用户都必须登录,并且他可以拥有不同的角色。通常,具有角色的列表将出现在客户端(以便能够显示/隐藏一些UI控件)和服务器端(链接到会话,以在服务器端进行两次相同的检查)。您不能信任来自客户端的角色,因为最终用户可能直接在浏览器中修改它们(即使在缩小JS的情况下它是非常复杂的任务)。这里有两个选项:1)使用服务器端会话2)模拟服务器端会话(在每个RPC调用中发送一些自定义会话令牌,然后在每次用户角色时重新加载)。我更喜欢第一个选项,它使我能够重用现有的安全库,如Spring Security(节省了大量的时间/错误)。您可以根据需要选择第二个选项(您的项目有足够的资源来实现和测试您自己的服务器端会话仿真和安全方面的实现,使完全无状态的服务器端)。

总结:

  1. 您有一些敏感的会话数据 - >将它们存储在服务器会话中 - >你需要会话聚类
  2. 您的会话数据不敏感/根本没有它们 - >将它们存放在浏览器中/没有库存 - >您不需要会话和会话群集
  3. 您有一些敏感的会话数据 - >将它们存储在服务器端,并使用一些自定义会话仿真技术为每个请求重新加载它们 - >您不需要会话群集(但是您需要更多时间来完成选项1)。
  4. 修改 在上面的代码示例中,您可能会遇到以下潜在问题:

    1. 用户以user1身份登录(具有ROLE_USER权限)。
    2. 他在内部使用user2生成某种请求(具有ROLE_ADMIN权限)以及只有在拥有ROLE_ADMIN权限时才能执行的操作。
    3. 即使user1没有相应的权限,也会执行此操作。
    4. 问题的原因是用户对象来自不受信任的来源(请求),并且可以由最终用户修改。我可以将他存储在服务器端,例如使用服务器端会话,而不是将他存储在客户端:

      public class BackOfficeServlet extends HttpServlet {
          @Override
          public void doPost(HttpServletRequest request, HttpServletResponse response) {
              User u = getUserFromSession(request.getSession(false));
              Action a = getActionFromRequest(request);
      
              if(UserActionAuthenticator.actionIsAllowed(u, a))
                  a.execute(u, request);
          }
      }
      

      现在我们可以信任用户对象,因为最终用户无法更改会话对象。