Building a façade with spring which calls another server and returns its response

913 views Asked by At

For an application I need to create a security façade in Spring 4.x.

This thiny layer must accepts any request from our mobile application and execute a security check for the provided token (with openId and Oauth).

Upon a successful validation, the request needs to be forwarded to the backend application, which does not need to be aware of the security token mechanism.

Thus, the flow will be something like this: security_facade_url/path/of/the/request

With a header that indicates the backend to invoke upon successful validation of the token

Upon successful validation the security façade sends a request to the backend URL backend_application_url/path/of/the/request

The façade must not have a controller which maps to any possible path of the request, but must call the request on the correct backend server, based on a value in the header of the request. Then return this response to the user.

What I have so far is an implementation of the HandlerInterceptor. This interceptor works, however, I am not really happy with the way I need to avoid the afterCompletion by throwing an exception in the postHandle method. If I do not throw an error, the default error page is appended to the correct response in the afterCompletion step.

This is my code so far:

public class RequestProcessingInterceptor implements HandlerInterceptor {    
private final Logger log = LoggerFactory.getLogger(RequestProcessingInterceptor.class);

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
    log.info("Doing some security stuff now ...");

    log.warn("... security ok ... since I am not really checking stuff");
    return true;
}

public void postHandle(HttpServletRequest request,
                       HttpServletResponse response, Object handler,
                       ModelAndView modelAndView) throws Exception {
    log.info("Forwarding request and sending that info back ...");

    ClientConfig config = new DefaultClientConfig();
    Client client = Client.create(config);
    WebResource service = client.resource(UriBuilder.fromUri("http://localhost:8080").build());

    response.setContentType("application/json");
    response.getWriter().write(service.path(modelAndView.getModel().get("path").toString()).accept("application/json").get(String.class));
    response.setStatus(200);

    throw new Exception("Need to avoid the execution of the afterCompletion. Only way to do so is by throwing an exception...");
}

public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

}

}

Is there a more proper way to intervene with the Spring livecycle or obtain the behaviour as described above?

2

There are 2 answers

0
zip4ever On

Found a better solution. For what I need, I do not need to manipulate the results in an interceptor.

A much cleaner way is to define a Controller which maps with the request methods.

@RequestMapping(method = {RequestMethod.GET, RequestMethod.PUT, RequestMethod.POST})
public void handleRequest(HttpServletRequest request, HttpServletResponse response) { // code omitted }
0
Serge Ballesta On

You should not try to avoid the call to afterCompletion. Just implement an empty method and let SpringFramework call it.

Provided your controller returns null indicating that no view has to be called, it should work with a smoother Spring integration.

But I cannot understand why you use Spring MVC here. As you only interact with low level HttpServletRequest and HttpServletResponse, you could as well use :

  • a dedicated servlet in charge to relay the request and response to the backend and write the returned value in the response
  • a filter that would do the security stuff before passing request to filter chain