Frage

I am using RequestFactory with GWT. It all working fine. I have a RequestContext interface that point to my DAO methodes.

Now I want to implement some kind of security check before calling the DAO. The first thing that comes to my mind is to use a FrontController and centralize the security in it, but I don't know to implement it with the RequestFactory. Any thought ?

War es hilfreich?

Lösung 2

Here's how I implemented the security checking:

On the server side I check to see that every RequestFactory request is associated with a user who has previously logged in. To do this, the web.xml file (in the war/WEB-INF directory) must have a mapping for the servlet class. Here's the entry from the web.xml file:

<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>

The RFERequestFactoryServlet class contains the following code:

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;
}

}

On the client side I needed to intercept every RequestFactory response to check for the SC_UNAUTHORIZED error. You have to tell the RequestFactory object to use a specific RequestTransport in the RequestFactory#initialize invocation, like this:

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

My RFERequestTransport class extends the DefaultRequestTransport class:

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));
}

}

When RequestFactory creates a request callback it calls my method, which creates my own version of a RequestCallback. If the user is logged in (as determined by the servlet) then it just performs the normal RequestFactory processing; otherwise, I go through the login process with the user. Part of the login process involves communication with the server to verify the login ... if the login is successful then I create an object on the server and store a reference to it in the "User" attribute - this is then checked in the userIsLoggedIn method in the servlet class.

Andere Tipps

If you want to test whether the user is authenticated, you can use a servlet filter on the server-side and a custom RequestTransport on the client-side. See the guice-rf-activity archetype at https://github.com/tbroyer/gwt-maven-archetypes for an example.

You can also check on the method-level by using a custom ServiceLayerDecorator and implementing the invoke method, calling report() when the user isn't authorized/authenticated (and handling the onFailure on the client-side). I implemented such a thing, that authorized the user based on @RolesAllowed annotations on the service method or class: https://gist.github.com/tbroyer/6091533

Setup a filter in your web.xml so as every RF request is filtered to validate the session.

<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>

Here you have an example class, checking if a certain parameter is in session which could be set in the login process to your app, this is just an example, you could use your own mechanism.

  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);
      }

    }
  }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top