Tuesday, January 10, 2012

Using a MultpartRequestResolver with Spring and using Spring Security concurrently

Update: This will not work with Spring 3.1. This is due to the ServletRequestMethodArgumentResolver being added by default prior to custom argument resolvers in a private method in the RequestMappingHandlerAdapter (getDefaultArgumentResolvers).

When using Spring Security, the CommonsMultipartResolver will not work. Why? Because the MultipartHttpServletRequest will be wrapped in a SecurityContextHolderAwareRequestWrapper, and will not be matched.
Of course, we don't want to fall back to just taking an HttpServletRequest as a parameter in our RequestMapping and parsing it out, we need to work smarter than that!
The best solution I could come up with is registering a custom WebArgumentResolver (below). But any readers out there have a better solution, please share!
Resolver:

2 comments:

  1. Is it possible to find about this problem in Spring documentation?
    I have found the same problem in my application, but I need more explanation for resolving it.

    ReplyDelete
  2. I use a lot of security filters and found more than one wrapper class around the request. Here's how I did it:

    // peeling wrappers because of Spring Security filters used
    ServletRequest originalRequest = request;
    MultipartHttpServletRequest multipartRequest = null;
    while (originalRequest instanceof ServletRequestWrapper) {
    log.debug("Unwrapping " + originalRequest.getClass().getName());
    originalRequest = ((ServletRequestWrapper)originalRequest).getRequest();
    }
    log.debug("Original request type: " + originalRequest.getClass().getName());
    if (originalRequest instanceof MultipartHttpServletRequest)
    multipartRequest = (MultipartHttpServletRequest)(originalRequest);
    else {
    multipartRequest = commonsMultipartResolver.resolveMultipart((HttpServletRequest)originalRequest);
    }

    ReplyDelete