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:
public class SecurityContextWrappedMultipartRequestArgumentResolver implements WebArgumentResolver {
private final CommonsMultipartResolver commonsMultipartResolver;
public SecurityContextWrappedMultipartRequestArgumentResolver(){
this.commonsMultipartResolver = new CommonsMultipartResolver();
}
@Override
public Object resolveArgument(MethodParameter methodParameter, NativeWebRequest webRequest) throws Exception {
if (MultipartHttpServletRequest.class.equals(methodParameter.getParameterType())) {
Object object = webRequest.getNativeRequest();
if (! (object instanceof SecurityContextHolderAwareRequestWrapper)) {
return UNRESOLVED;
}
HttpServletRequest request = (HttpServletRequest) object;
if (!ServletFileUpload.isMultipartContent(request)) {
return UNRESOLVED;
}
SecurityContextHolderAwareRequestWrapper requestWrapper = (SecurityContextHolderAwareRequestWrapper) request;
return commonsMultipartResolver.resolveMultipart(requestWrapper);
}
return UNRESOLVED;
}
}
Then we just wire it up into our HandlerAdapter (your config may vary):
@Bean
public HandlerAdapter handlerAdapter() {
final AnnotationMethodHandlerAdapter handlerAdapter = new AnnotationMethodHandlerAdapter();
handlerAdapter.setCustomArgumentResolver(new SecurityContextWrappedMultipartRequestArgumentResolver());
handlerAdapter.setAlwaysUseFullPath(true);
List<HttpMessageConverter<?>> converterList = new ArrayList<HttpMessageConverter<?>>();
converterList.addAll(Arrays.asList(handlerAdapter.getMessageConverters()));
converterList.add(jibxHttpMessageConverter);
converterList.add(gsonHttpMessageConverter);
converterList.add(csvLocalizationConverter);
converterList.add(protobufLocalizationConverter);
handlerAdapter.setMessageConverters(converterList.toArray(new HttpMessageConverter>[converterList.size()]));
return handlerAdapter;
}
0 comments:
Post a Comment