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?
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.
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.
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.
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.
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(); ...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With