2012-05-14 10 views
7

Impossibile accedere alle informazioni Spring Security durante un post multipart servlet. Le informazioni sulla sicurezza primaverile sono disponibili durante i normali metodi get e post, ma non sono disponibili per un metodo di post multipart. Ho provato senza successo ad accedere a queste informazioni di sicurezza direttamente tramite SecurityContextHolder.getContext(). GetAuthentication() e attraverso un servizio inserito che accede a SecurityContextHolder.getContext(). GetAuthentication().Impossibile accedere alle informazioni Spring Security durante un post multipart servlet

Ho implementato anche HttpRequestHandler e ServletWrappingController. Ancora una volta, sono stato in grado di iniettare correttamente i bean a molla e accedere alle informazioni di Spring Security per i normali metodi get e post, ma non sono stato in grado di accedere alle informazioni Spring Security per i post multipart. So che ci sono nuove funzionalità MultiPart incorporate in Spring 3.0 ma poiché il nostro sito Web richiederà l'accesso completo al flusso di caricamento dei file, non potrò usarle. Per questo motivo, mi sto concentrando su HttpServlet, HttpRequestHandler e ServletWrappingController.

Il codice che sto postando qui è tutto il codice di test scritto per risolvere questo specifico problema che sto affrontando con informazioni di sicurezza non disponibili durante un caricamento multipart (non inteso per essere di qualità di produzione). È per un HttpServlet.

Per favore fatemi sapere se c'è qualcosa che sto sbagliando. O se no, se c'è una soluzione alternativa o un modo migliore per realizzare un caricamento multipart con accesso alle informazioni di Spring Security mantenendo l'accesso al flusso di caricamento del file? Ogni aiuto che qualcuno può offrire con questo problema sarà molto apprezzato!

Di seguito è riportato il codice del servlet di test. Commenti qui sotto come a ciò che funziona e ciò che non è basato su un utente registrato per il sito web utilizzando Primavera di sicurezza 3.1:

//many import statements not displayed 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.web.context.support.SpringBeanAutowiringSupport; 

import org.springframework.security.core.GrantedAuthority; 
import org.springframework.security.core.context.SecurityContextHolder; 

public class UploadServlet extends HttpServlet { 

    public void service(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException { 
     super.service(req, res); 
    } 

    public void init(ServletConfig config) throws ServletException { 
     super.init(config); 

     SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, 
      config.getServletContext()); 
    } 


    //The following is always injected and available 
    //however, it only returns valid security information for regular get and post methods, 
    //not for multipart post methods 
    @Autowired 
    private CustomUserService customUserService; 

    //The following is always injected and available and always returns the expected data 
    @Autowired 
    private GuideService guideService; 

    //the following does not work when the client issues a multipart post, it does work for non-multipart 
    public boolean getAuthenticated(){ 
     boolean authorized = false; 

     for (GrantedAuthority authority : SecurityContextHolder.getContext().getAuthentication().getAuthorities()) { 
      if(authority.getAuthority().equals("ROLE_USER") || authority.getAuthority().equals("ROLE_ADMIN")) { 
       authorized = true; 
       break; 
      } 
     } 

     return authorized; 
    } 


    //The following test get method works fine 
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {   
     if(getAuthenticated()){ 
      PrintWriter out = resp.getWriter(); 
      out.write("<h1>Guide Info</h1><br/>"); 
      Guide guide = guideService.findById(2l); 
      out.write(guide.getName() + "<br/>"); 
      out.write(guide.getDescription() + "<br/>"); 
      out.write("UserName: " + customUserService.getCurrentUser().getUsername() + "<br/>"); 
     } 
     else{ 
      PrintWriter out = resp.getWriter(); 
      out.write("<h1>You're not authorized</h1><br/>"); 
     } 
    } 


    //This post method 
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 

     //the following always works, whether the clients posts using multipart or not  
     String guideName = guideService.findById(2l).getName(); 

     //the following does not work when the client issues a multipart post, it does work for non-multipart 
     String userName = customUserService.getCurrentUser().getUsername(); 

     //the following does not work when the client issues a multipart post, it does work for non-multipart 
     if(getAuthenticated()){ 
      String responseString = RESP_SUCCESS; 
      boolean isMultipart = ServletFileUpload.isMultipartContent(req); 

      if (isMultipart) { 
       ServletFileUpload upload = new ServletFileUpload(); 

       //commmons fileupload code 

      // Not a multi-part MIME request. 
      else { 
       //... 
      } 
      //... 
     } 
     else{ 
      //... 
     } 


    } 

} 

Qui è la quota di competenza di web.xml:

<servlet> 
    <servlet-name>fgm</servlet-name> 
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
    <init-param> 
     <param-name>contextConfigLocation</param-name> 
     <param-value>WEB-INF/spring/webmvc-config.xml</param-value> 
    </init-param> 
    <load-on-startup>1</load-on-startup> 
</servlet> 

<servlet-mapping> 
    <servlet-name>fgm</servlet-name> 
    <url-pattern>/</url-pattern> 
</servlet-mapping> 

<servlet> 
    <servlet-name>UploadServlet</servlet-name> 
    <servlet-class>com.guides.servlet.UploadServlet</servlet-class> 
</servlet> 
<servlet-mapping> 
    <servlet-name>UploadServlet</servlet-name> 
    <url-pattern>/upload</url-pattern> 
</servlet-mapping> 
+0

È possibile aggiungere la parte di web.xml che mostra la configurazione di Spring Security? – Ritesh

+0

Perché stai mappando le richieste a 'UploadServlet' in web.xml piuttosto che nella configurazione di Spring? –

risposta

0

Questo potrebbe aiutare, se si sta utilizzando Spring MVC: dettagli

{ 
    @RequestMapping(method = RequestMethod.POST, value = "/some/post/url") 
    public void postFile(MultipartHttpServletRequest request) { 
    MultipartFile multipartFile = request.getFileMap().get("fileControlName"); 
    ... 
    } 
} 
+0

Dovresti spiegare come questo risolve il problema. –

0

di sicurezza come previsto dalla SecurityContextHolder sono (per impostazione predefinita) memorizzati in un ThreadLocal.

Il servlet di caricamento crea un nuovo thread per gestire multiparts? Provare a cambiare il SecurityContextHolderStrategy a MODE_INHERITABLETHREADLOCAL

problemi simili: How to set up Spring Security SecurityContextHolder strategy?

0

Potrebbe essere la pena di verificare come il vostro cliente sta eseguendo il palo più parti, si sta utilizzando un diverso meccanismo/biblioteca al tuo post di serie?

Se dovessi indovinare, direi che il codice cliente non si autentica correttamente per il caso d'uso multi-parte.

E.g. Utilizzo di Java standard per il normale post e librerie Apache per il post multipart e dimenticando di impostare le intestazioni http appropriate quando si utilizza la roba di Apache.

2

Posso confermare che Spring 3.0.x e Spring Security 3.0.x funzionano insieme con post multipart e funzionano con altri tipi di richieste. Ho avuto un comportamento simile e, nel nostro caso, il filtro di sicurezza non è stato applicato alla richiesta a causa del nostro errore nei mapping dei filtri.

Puoi pubblicare le parti del tuo sito web.xml che definisce il filtro di sicurezza e lo associa ai percorsi desiderati?

Problemi correlati