Il token CSRF Spring non funziona, quando la richiesta da inviare è una richiesta multipart

Io uso,

  • Spring Framework 4.0.0 RELEASE (GA)
  • Spring Security 3.2.0 RELEASE (GA)
  • Struts 2.3.16

In cui, utilizzo un token di sicurezza integrato per proteggersi dagli attacchi CSRF.

La forma Struts ha il seguente aspetto.

   

Il codice HTML generato è il seguente.

 

Funziona bene, a meno che la richiesta non sia multipart in quel caso, la richiesta termina con il codice di stato 403.

Stato HTTP 403 – Il token CSRF non valido ‘null’ è stato trovato sul parametro di richiesta ‘_csrf‘ o intestazione ‘X-CSRF-TOKEN’.

digitare lo stato report

messaggio Token CSRF non valido ‘null’ trovato sul parametro di richiesta ‘_csrf’ o intestazione ‘X-CSRF-TOKEN’.

descrizione L’accesso alla risorsa specificata è stato proibito.

Il file spring-security.xml è il seguente.

            <!----> <!---->                              

Quindi, dove cercare questo token, quando una richiesta è multipart? (Questo non dovrebbe essere collegato a Struts affatto).

L’implementazione di UserDetailsService può essere trovata in questa mia prima domanda, se necessario.


Posizionare MultipartFilter prima che Spring Security non sia stato d’aiuto.

Il file web.xml il seguente aspetto.

    contextConfigLocation  /WEB-INF/applicationContext.xml /WEB-INF/spring-security.xml    MultipartFilter org.springframework.web.multipart.support.MultipartFilter   springSecurityFilterChain org.springframework.web.filter.DelegatingFilterProxy   MultipartFilter /*   springSecurityFilterChain /*   AdminLoginNocacheFilter filter.AdminLoginNocacheFilter   AdminLoginNocacheFilter /admin_login/*   NoCacheFilter filter.NoCacheFilter   NoCacheFilter /admin_side/*   org.springframework.web.context.ContextLoaderListener   Description org.springframework.web.context.request.RequestContextListener   org.springframework.security.web.session.HttpSessionEventPublisher   struts2 org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter  struts.devMode true    struts2 /*    30    index.jsp   

Funziona solo quando il token è aggiunto come parametro query-string come segue, che è tuttavia scoraggiato.

  ...  

Se stai usando @annotations e la vista jsp in questo modo:

   ...  ...   

questo può aiutare:

AppConfig.java:

 @EnableWebMvc @Configuration @Import({ SecurityConfig.class }) public class AppConfig { @Bean(name = "filterMultipartResolver") public CommonsMultipartResolver filterMultipartResolver() { CommonsMultipartResolver filterMultipartResolver = new CommonsMultipartResolver(); filterMultipartResolver.setDefaultEncoding("utf-8"); // resolver.setMaxUploadSize(512000); return filterMultipartResolver; } ... 

SecurityConfig.java estende WebSecurityConfigurerAdapter ed è la configurazione per SpringSecurity

Il filtro multipart / form-data (MultipartFilter) deve essere registrato prima di SecurityConfig che abilita CSRF. Puoi farlo con questo:

SecurityInitializer.java:

 public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer { @Override protected void beforeSpringSecurityFilterChain(ServletContext servletContext) { super.beforeSpringSecurityFilterChain(servletContext); // CSRF for multipart form data filter: FilterRegistration.Dynamic springMultipartFilter; springMultipartFilter = servletContext.addFilter( "springMultipartFilter", new MultipartFilter()); springMultipartFilter.addMappingForUrlPatterns(null, false, "/*"); } } 

In questo caso, poiché si tratta di una richiesta multipart in cui il token CSRF non è disponibile per la sicurezza Spring a meno che MultipartFilter con MultipartResolver sia configurato correttamente in modo che la richiesta multipart possa essere elaborata da Spring.

MulipartResolver nel file applicationContext.xml deve essere registrato come segue

    

Il valore dell’attributo -1 di maxUploadSize non pone alcun limite alle dimensioni del file caricato. Questo valore può variare a seconda dei requisiti. Nel caso di più file, la dimensione del file è la dimensione di tutti i file caricati.


Anche,

 /* 

di di MultipartFilter deve essere cambiato in

 /* 

Questo è un bug nella documentazione .

Questo funzionerà bene, nel caso, è solo Spring MVC.

ma se è un’integrazione di Spring e Struts (2), incorre in un altro problema nella class di azioni Struts associata. Le informazioni del file caricato saranno null nelle classi di azioni Struts associate.

Per risolvere questo particolare problema, vedere questa risposta per personalizzare una richiesta multipart .

Ho risolto questo problema:

  • inviare il file multiparte usando vanilla javascript, come nella guida di Mozilla
  • aggiungendo il token _csrf nell’intestazione HTML, in meta tag, come nella linea guida Spring per l’ invio del token CSRF con Ajax
  • invece di usare jquery, aggiungendolo direttamente all’object XHR

     var csrfToken = $("meta[name='_csrf']").attr("content"); var csrfHeader = $("meta[name='_csrf_header']").attr("content"); XHR.setRequestHeader(csrfHeader, csrfToken); XHR.setRequestHeader('Content-Type','multipart/form-data; boundary=' + boundary); XHR.send(data); 

È ansible disabilitare csrf – httpSecurity.csrf (). Disable ();

  @Configuration public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity httpSecurity) throws Exception { ... httpSecurity.csrf().disable(); ... } }