Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Security & Multipart requests

Tags:

I have a @Controller protected with Spring Security and OAuth2 in which I am trying to let my users upload a file:

@Controller @RequestMapping(value = "/api/image") public class ImageController {      @PreAuthorize("hasAuthority('ROLE_USER')")     @RequestMapping(value = "/upload", method = RequestMethod.PUT)     public @ResponseBody Account putImage(@RequestParam("title") String title, MultipartHttpServletRequest request, Principal principal){         // Some type of file processing...         System.out.println("-------------------------------------------");         System.out.println("Test upload: " + title);         System.out.println("Test upload: " + request.getFile("file").getOriginalFilename());         System.out.println("-------------------------------------------");          return ((Account) ((OAuth2Authentication) principal).getPrincipal());     } } 

When I try to upload a file and title, I get the following exception. I am setting the Content-Type header to multipart/form-data.

java.lang.IllegalStateException: Current request is not of type [org.springframework.web.multipart.MultipartHttpServletRequest]: SecurityContextHolderAwareRequestWrapper[ FirewalledRequest[ org.apache.catalina.connector.RequestFacade@1aee75b7]]     at org.springframework.web.servlet.mvc.method.annotation.ServletRequestMethodArgumentResolver.resolveArgument(ServletRequestMethodArgumentResolver.java:84)     at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:75)     at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:156)     at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:117) 

How can I do file uploads behind Spring Security? It seems like the request never gets turned into a MultiPartHttpServerRequest and so it doesn't work?

If I change my method signature to take a @RequestParam MultipartFile, then I get an exception like:

DEBUG DefaultListableBeanFactory - Returning cached instance of singleton bean 'imageController' DEBUG ExceptionHandlerExceptionResolver - Resolving exception from handler [public com.tinsel.server.model.Account com.tinsel.server.controller.ImageController.putImage(java.lang.String,org.springframework.web.multipart.MultipartFile,java.security.Principal)]: java.lang.IllegalArgumentException: Expected MultipartHttpServletRequest: is a MultipartResolver configured? DEBUG ResponseStatusExceptionResolver - Resolving exception from handler [public com.tinsel.server.model.Account com.tinsel.server.controller.ImageController.putImage(java.lang.String,org.springframework.web.multipart.MultipartFile,java.security.Principal)]: java.lang.IllegalArgumentException: Expected MultipartHttpServletRequest: is a MultipartResolver configured? DEBUG DefaultHandlerExceptionResolver - Resolving exception from handler [public com.tinsel.server.model.Account com.tinsel.server.controller.ImageController.putImage(java.lang.String,org.springframework.web.multipart.MultipartFile,java.security.Principal)]: java.lang.IllegalArgumentException: Expected MultipartHttpServletRequest: is a MultipartResolver configured? DEBUG DispatcherServlet - Could not complete request java.lang.IllegalArgumentException: Expected MultipartHttpServletRequest: is a MultipartResolver configured?     at org.springframework.util.Assert.notNull(Assert.java:112) 

...but I do have a MultipartResolver configured in my XML:

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">     <property name="maxUploadSize" value="268435456"/> <!-- 256 megs --> </bean> 

I did see this blog post about getting this working under Spring 3.0 - but I'm trying to stay more up to date and am using 3.1 currently. Is there perhaps an updated fix?

like image 548
Matthew Runo Avatar asked Feb 25 '13 00:02

Matthew Runo


People also ask

What is Spring Security for?

Spring Security is a powerful and highly customizable authentication and access-control framework. It is the de-facto standard for securing Spring-based applications. Spring Security is a framework that focuses on providing both authentication and authorization to Java applications.

What is Spring Security with example?

Spring Security Configuration is using Builder Pattern and based on the authenticate method, some of the methods won't be available later on. For example, auth. userDetailsService() returns the instance of UserDetailsService and then we can't have any other options, such as we can't set DataSource after it.

What is Spring Security and JWT?

JSON Web Token or JWT, as it is more commonly called, is an open Internet standard (RFC 7519) for securely transmitting trusted information between parties in a compact way. The tokens contain claims that are encoded as a JSON object and are digitally signed using a private secret or a public key/private key pair.


2 Answers

The problem is that I'm using a PUT instead of a POST. Commons FileUpload is hard coded to only accept POST requests for files.

Check the isMultipartContent method there. To fix this, either use a POST or extend that class and override that method to work how you like.

I opened FILEUPLOAD-214 for this issue.

like image 119
Matthew Runo Avatar answered Oct 04 '22 06:10

Matthew Runo


To solve the problem, do not use spring MultiPartHttpServerRequest, instead taking the request as HttpServletRequest, using the apache commons fileupload library to parse the request from PUT method, and processing the file. Here are some sample code:

ServletFileUpload fileUpload = new ServletFileUpload(new DiskFileItemFactory()); List<FileItem> fileItems = fileUpload.parseRequest(httpServletRequest); InputStream in = fileItems.get(0).getInputStream(); ... 
like image 25
steve chen Avatar answered Oct 04 '22 04:10

steve chen