【问题标题】:FrontController with RequestFactory in GWT在 GWT 中使用 RequestFactory 的 FrontController
【发布时间】:2013-03-26 15:17:01
【问题描述】:

我将 RequestFactory 与 GWT 一起使用。一切正常。我有一个指向我的 DAO 方法的 RequestContext 接口。

现在我想在调用 DAO 之前实施某种安全检查。我首先想到的是使用 FrontController 并将安全性集中在其中,但我不知道用 RequestFactory 来实现它。有什么想法吗?

【问题讨论】:

  • 您要进行什么样的安全检查?测试用户身份验证?
  • 基本上我想检查用户是否有活动会话。

标签: gwt requestfactory front-controller


【解决方案1】:

如果要测试用户是否通过身份验证,可以在服务器端使用 servlet 过滤器,在客户端使用自定义 RequestTransport。有关示例,请参见 https://github.com/tbroyer/gwt-maven-archetypesguice-rf-activity 原型。

您还可以通过使用自定义ServiceLayerDecorator 并实现invoke 方法来检查方法级别,当用户未经授权/验证时调用report()(并在客户端处理onFailure -边)。我实现了这样一个东西,根据服务方法或类上的@RolesAllowed注解授权用户:https://gist.github.com/tbroyer/6091533

【讨论】:

    【解决方案2】:

    以下是我实施安全检查的方式:

    在服务器端,我检查每个RequestFactory 请求都与以前登录的用户相关联。为此,web.xml 文件(在 war/WEB-INF 目录中)必须有一个servlet 类的映射。这是来自web.xml 文件的条目:

    <servlet>
      <servlet-name>requestFactoryServlet</servlet-name>
      <servlet-class>org.greatlogic.rfexample2.server.RFERequestFactoryServlet</servlet-class>
      <init-param>
        <param-name>symbolMapsDirectory</param-name>
        <param-value>WEB-INF/classes/symbolMaps/</param-value>
      </init-param>
    </servlet>
    <servlet-mapping>
      <servlet-name>requestFactoryServlet</servlet-name>
      <url-pattern>/gwtRequest</url-pattern>
    </servlet-mapping>
    

    RFERequestFactoryServlet 类包含以下代码:

    public class RFERequestFactoryServlet extends RequestFactoryServlet {
    
    @Override
    protected void doPost(final HttpServletRequest request, final HttpServletResponse response)
      throws IOException, ServletException {
      if (!userIsLoggedIn(request)) {
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
      }
      else {
        super.doPost(request, response);
      }
    }
    
    private boolean userIsLoggedIn(final HttpServletRequest request) {
      boolean result = false;
      HttpSession session = request.getSession();
      if (session != null) {
        User user = (User)session.getAttribute("User");
        result = user != null;
      }
      return result;
    }
    
    }
    

    在客户端,我需要拦截每个 RequestFactory 响应以检查 SC_UNAUTHORIZED 错误。您必须告诉RequestFactory 对象在RequestFactory#initialize 调用中使用特定的RequestTransport,如下所示:

    MyRequestFactory requestFactory = GWT.create(MyRequestFactory.class);
    requestFactory.initialize(eventBus, new RFERequestTransport());
    

    我的RFERequestTransport 类扩展了DefaultRequestTransport 类:

    public class RFERequestTransport extends DefaultRequestTransport {
    
    private final class RFERequestCallback implements RequestCallback {
    
    private RequestCallback _requestCallback;
    
    private RFERequestCallback(final RequestCallback requestCallback) {
      _requestCallback = requestCallback;
    }
    
    @Override
    public void onError(final Request request, final Throwable exception) {
      _requestCallback.onError(request, exception);
    }
    
    @Override
    public void onResponseReceived(final Request request, final Response response) {
      if (response.getStatusCode() == Response.SC_UNAUTHORIZED) {
        // the login processing goes here
      }
      else {
        _requestCallback.onResponseReceived(request, response);
      }
    }
    
    } // end of the RFERequestCallback class
    
    @Override
    protected RequestCallback createRequestCallback(final TransportReceiver receiver) {
      return new RFERequestCallback(super.createRequestCallback(receiver));
    }
    
    }
    

    RequestFactory 创建请求回调时,它会调用我的方法,该方法会创建我自己的RequestCallback 版本。如果用户已登录(由 servlet 确定),则它只执行正常的RequestFactory 处理;否则,我将与用户一起完成登录过程。登录过程的一部分涉及与服务器的通信以验证登录......如果登录成功,那么我在服务器上创建一个对象并将对它的引用存储在“用户”属性中 - 然后在@中检查servlet 类中的 987654340@ 方法。

    【讨论】:

    • 如何管理第一次登录请求?因为会话尚未创建
    • @Moh 在RFERequestFactoryServlet#userIsLoggedIn 我正在执行HttpServletRequest#getSession。此方法的 JavaDoc 声明:返回与此请求关联的当前会话,或者如果请求没有会话,则创建一个。
    • 我了解HttpSession 的部分。但是当从会话中获取用户时,它可以为空,如果没有用户登录,这将是正常的。现在我的问题是,当我在 DAO 中调用进行登录的方法时,调用将通过RFERequestFactoryServlet#userIsLoggedIn 并且由于会话中还没有用户,登录请求不会通过,并且将显示登录视图。即使没有用户在会话中,如何让登录请求通过?
    • @Moh 您是否担心流程中存在循环...也就是说,当您处理用户对登录请求的响应时,它只会导致另一个SC_UNAUTHORIZED 响应来自小服务程序? (顺便说一句,请在您的 cmets 中使用“@”,以便我在电子邮件中看到它们)。
    • @Moh 我不知道这是否有帮助,但在我实现登录过程的代码中,我使用 GWT RPC 发送用户的用户名和密码,而不是使用 RequestFactory,即我不使用 DAO 进行登录。我有一个实现此方案的示例项目(尽管在此示例中它不包括失败登录的操作)...我在我的博客 here 中描述了该项目。
    【解决方案3】:

    在您的 web.xml 中设置一个过滤器,以便过滤每个 RF 请求以验证会话。

    <filter>
      <filter-name>AuthFilter</filter-name>
      <filter-class>my.namespace.AuthFilter</filter-class>
    </filter>
    <filter-mapping>
      <filter-name>AuthFilter</filter-name>
      <url-pattern>/gwtRequest</url-pattern>
    </filter-mapping>
    

    这里有一个示例类,检查某个参数是否在会话中,该参数可以在您的应用程序的登录过程中设置,这只是一个示例,您可以使用自己的机制。

      public class AuthFilter implements Filter {
    
        public void doFilter(ServletRequest servletRequest,
            ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
    
          HttpServletRequest req = (HttpServletRequest) servletRequest;
          HttpServletResponse resp = (HttpServletResponse) servletResponse;
    
          if (req.getSession().getAttribute("VALID_SESSION") == null) {
            resp.sendError(HttpServletResponse.SC_UNAUTHORIZED);
            return;
          }
    
          if (null != filterChain) {
            filterChain.doFilter(req, resp);
          }
    
        }
      }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-02-02
      • 1970-01-01
      • 2013-02-05
      • 2012-05-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-26
      相关资源
      最近更新 更多