0

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 ?

Momo
  • 2,471
  • 5
  • 31
  • 52

3 Answers3

3

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

Thomas Broyer
  • 64,353
  • 7
  • 91
  • 164
1

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

    }
  }
Andy King
  • 1,632
  • 2
  • 20
  • 29
Manolo Carrasco Moñino
  • 9,723
  • 1
  • 22
  • 27
1

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.

Andy King
  • 1,632
  • 2
  • 20
  • 29
  • How do you manage the first login request ? because the session is not created yet – Momo Apr 02 '13 at 16:11
  • @Moh In `RFERequestFactoryServlet#userIsLoggedIn` I am executing `HttpServletRequest#getSession`. The JavaDoc for this method states: Returns the current session associated with this request, or if the request does not have a session, creates one. – Andy King Apr 02 '13 at 22:16
  • I understand the part for `HttpSession`. But when a user is fetched from the session, it can be null, that would be normal if no user has been logged in. Now my problem is when I call the method in the DAO that does the login, the call would be processed throught `RFERequestFactoryServlet#userIsLoggedIn` and because there is no user in the session yet, the login request wouldn't go throught and the login view will be displayed. How to let the login request go throught even no user is in the session ? – Momo Apr 03 '13 at 17:42
  • @Moh Are you concerned that there is a loop in the process ... that is, when you process the user's response to the login request is processed it will just cause another `SC_UNAUTHORIZED` response from the servlet? (btw, please use the "@" in your comments so that I see them in email). – Andy King Apr 06 '13 at 16:41
  • @Moh I don't know whether this will help, but in my code that implements the login process I send the user's username and password using GWT RPC, and not using `RequestFactory`, that is, I don't use a DAO for logging in. I have an example project that implements this scheme (although it doesn't include actions for failed logins in this example) ... I describe the project in my blog, [here](http://greatlogic.com/?p=264). – Andy King Apr 06 '13 at 16:50
  • Yes I was concerned by the loop problem...Finally I did the login process in a servlet separately. Thanks – Momo Apr 07 '13 at 16:23