Sécurité de printemps et demandes multiparties

j'ai un @ Controller protégé avec Spring Security et OAuth2 dans lequel j'essaie de laisser mes utilisateurs charger un fichier:

@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());
    }
}

Quand j'essaie de télécharger un fichier et le titre, j'obtiens l'exception suivante. Je mets l'en-tête Content-Type à 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)

Comment puis-je télécharger des fichiers derrière la sécurité du printemps? Il semble que la requête ne se transforme jamais en Multiparthttpserrequest et donc ça ne fonctionne pas?

si je change mon signature de la méthode de prendre un @RequestParam MultipartFile, puis-je obtenir une exception de la forme:

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)

...mais j'ai un Multipartrésolver configuré dans mon XML:

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

je ne vois ce billet de blog à propos de la mise en œuvre de ce programme sous la rubrique printemps 3.0 - mais j'essaie de rester plus à jour et j'utilise 3.1 actuellement. Y a-t-il peut-être un correctif mis à jour?

23
demandé sur Matthew Runo 2013-02-25 04:45:09

4 réponses

le problème est que j'utilise un PUT au lieu d'un POST. Le fichier Commons Upload est codé de manière à n'accepter que les requêtes POST pour les fichiers.

Case isMultipartContent méthode il n'. Pour corriger ceci, utilisez un poteau ou étendez cette classe et outrepassez cette méthode pour travailler comme vous voulez.

j'ai ouvert FILEUPLOAD-214 pour ce problème.

25
répondu Matthew Runo 2013-02-26 16:55:08

pour résoudre le problème, n'utilisez pas spring MultiPartHttpServerRequest, mais prenez la requête comme HttpServletRequest, en utilisant la bibliothèque Apache commons fileupload pour analyser la requête de la méthode PUT et traiter le fichier. Voici un exemple de code:

ServletFileUpload fileUpload = new ServletFileUpload(new DiskFileItemFactory());
List<FileItem> fileItems = fileUpload.parseRequest(httpServletRequest);
InputStream in = fileItems.get(0).getInputStream();
...
3
répondu steve chen 2013-07-06 19:50:36

Dans Config.groovy

assurez-vous que multipart est activé,

// whether to disable processing of multi part requests
   grails.web.disable.multipart=false

dans controller ajouter la méthode Post

def upload(){
    MultipartHttpServletRequest mpr = (MultipartHttpServletRequest)request;
    if(request instanceof MultipartHttpServletRequest)
            {
                CommonsMultipartFile f = (CommonsMultipartFile) mpr.getFile("myFile");
                println f.contentType
                f.transferTo()
                if(!f.empty)
                    flash.message = 'success'
                else
                    flash.message = 'file cannot be empty'
            }
    else
    flash.message = 'request is not of type MultipartHttpServletRequest'}
2
répondu Nazeel 2014-07-21 18:53:09

you might take a look at https://github.com/joshlong/the-spring-tutorial qui a un exemple montrant comment afficher à un MVC de printemps avec un OAuth de sécurité de printemps activé. J'utilise même HTML5 drag and drop pour faire glisser l'image sur l'écran puis la soumettre via ajax au serveur.

-1
répondu Josh Long 2013-02-26 19:46:53