13

Sto tentando di configurare il server Spring con Spring Security 3.2 per poter eseguire una richiesta di accesso ajax.Come impostare il filtro Access-Control-Allow-Origin in modo problematico in Spring Security 3.2

ho seguito il video Spring Security 3.2 e un paio di posti, ma il problema è che sto ottenendo

No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:9000' is therefore not allowed access. 

Per le richieste di accesso (vedi sotto).

Ho creato una configurazione di CORSFilter e posso accedere alle risorse non protette nel mio sistema con le intestazioni appropriate aggiunte alla risposta.

La mia ipotesi è che non sto aggiungendo il CORSFilter alla catena del filtro di sicurezza o potrebbe essere troppo tardi nella catena. Qualsiasi idea sarà apprezzata.

WebAppInitializer

public class WebAppInitializer implements WebApplicationInitializer { 
    @Override 
    public void onStartup(ServletContext servletContext) { 
     WebApplicationContext rootContext = createRootContext(servletContext); 

     configureSpringMvc(servletContext, rootContext); 

     FilterRegistration.Dynamic corsFilter = servletContext.addFilter("corsFilter", CORSFilter.class); 
     corsFilter.addMappingForUrlPatterns(null, false, "/*"); 
    } 

    private WebApplicationContext createRootContext(ServletContext servletContext) { 
     AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext(); 

     rootContext.register(SecurityConfig.class, PersistenceConfig.class, CoreConfig.class); 

     servletContext.addListener(new ContextLoaderListener(rootContext)); 
     servletContext.setInitParameter("defaultHtmlEscape", "true"); 

     return rootContext; 
    } 


    private void configureSpringMvc(ServletContext servletContext, WebApplicationContext rootContext) { 
     AnnotationConfigWebApplicationContext mvcContext = new AnnotationConfigWebApplicationContext(); 
     mvcContext.register(MVCConfig.class); 

     mvcContext.setParent(rootContext); 
     ServletRegistration.Dynamic appServlet = servletContext.addServlet(
       "webservice", new DispatcherServlet(mvcContext)); 
     appServlet.setLoadOnStartup(1); 
     Set<String> mappingConflicts = appServlet.addMapping("/api/*"); 

     if (!mappingConflicts.isEmpty()) { 
      for (String s : mappingConflicts) { 
       LOG.error("Mapping conflict: " + s); 
      } 
      throw new IllegalStateException(
        "'webservice' cannot be mapped to '/'"); 
     } 
    } 

SecurityWebAppInitializer:

public class SecurityWebAppInitializer extends AbstractSecurityWebApplicationInitializer { 
} 

SecurityConfig:

richieste a /api/utenti - funzionano bene e vengono aggiunte le intestazioni Access-Control-Allow. Ho disabile CSRF e le intestazioni solo per assicurarsi che questo non è il caso

@EnableWebMvcSecurity 
@Configuration 
public class SecurityConfig extends WebSecurityConfigurerAdapter { 

@Autowired 
    protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception { 
     auth.inMemoryAuthentication() 
       .withUser("user").password("password").roles("USER"); 
    } 


    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http 
      .csrf().disable() 
      .headers().disable()     
      .authorizeRequests() 
        .antMatchers("/api/users/**").permitAll() 
        .anyRequest().authenticated() 
        .and() 
      .formLogin() 
       .loginPage("/login") 
       .permitAll() 
       .and() 
      .logout() 
       .permitAll(); 
    } 

CORFilter:

@Component 
public class CORSFilter implements Filter{ 
    static Logger logger = LoggerFactory.getLogger(CORSFilter.class); 

    @Override 
    public void init(FilterConfig filterConfig) throws ServletException { 
    } 

    @Override 
    public void doFilter(ServletRequest request, ServletResponse res, FilterChain chain) throws IOException, ServletException { 
     HttpServletResponse response = (HttpServletResponse) res; 
     response.setHeader("Access-Control-Allow-Origin", "*"); 
     response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); 
     response.setHeader("Access-Control-Max-Age", "3600"); 
     response.setHeader("Access-Control-Allow-Headers", "x-requested-with"); 
     chain.doFilter(request, response); 
    } 

    public void destroy() {} 
} 

Accesso Richiesta:

Request URL:http://localhost:8080/devstage-1.0/login 
Request Headers CAUTION: Provisional headers are shown. 
Accept:application/json, text/plain, */* 
Cache-Control:no-cache 
Content-Type:application/x-www-form-urlencoded 
Origin:http://127.0.0.1:9000 
Pragma:no-cache 
Referer:http://127.0.0.1:9000/ 
User-Agent:Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36 
Form Dataview sourceview URL encoded 
username:user 
password:password 
+0

È possibile aggiungere la configurazione di sicurezza Spring? –

risposta

17

Tutto quello che mancava era AddFilterBefore durante la configurazione della configurazione di sicurezza.

Quindi la versione finale è stata:

@EnableWebMvcSecurity 
@Configuration 
public class SecurityConfig extends WebSecurityConfigurerAdapter { 

    @Autowired 
    protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception { 
    auth.inMemoryAuthentication() 
     .withUser("user").password("password").roles("USER"); 
    } 


    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http 
      .addFilterBefore(new CORSFilter(), ChannelProcessingFilter.class) 

      .formLogin() 
       .loginPage("/login") 
       .and() 
      .authorizeRequests() 
       .anyRequest().authenticated(); 

e rimuovere il CORSFilter da WebAppInitializer

+0

Questo non sembra funzionare con Spring 4.2 :( – froginvasion

+0

non funziona per me con Spring boot 1.4.0 – WhiteWater

0

Lo so che è un po 'troppo tardi per rispondere alla tua domanda, ma pensato che potrebbe essere la pena di condividere. Nella vostra configurazione iniziale si erano registrati i metadati di configurazione initializer Primavera di sicurezza con il contesto radice:

rootContext.register(SecurityConfig.class, PersistenceConfig.class, CoreConfig.class); 

Quando si può fare questo, non hanno bisogno di come sarà accoppiare la catena dei filtri di sicurezza con il contesto applicazione web che non è richiesto. Invece, puoi semplicemente aggiungere la catena di filtri nel vecchio modo semplice registrando DelegatingFilterProxy come filtro. Ovviamente, dovrai mantenere l'ordine aggiungendo il filtro Cors prima di aggiungere la catena di filtri di sicurezza.

In questo modo, sarete in grado di utilizzare il magazzino CorsFilter (semplicemente aggiungendo i parametri init) fornito con il pacchetto org.apache.catalina.filters.Ad ogni modo, puoi anche mantenere la tua configurazione! :)

+0

Ehi, sono interessato a questo. Sono nei guai con un'applicazione di un fornitore, e ho bisogno di aggiungere cors filtro Potresti guidarmi un po 'Cosa intendi con: (solo aggiungendo i parametri init) .Voglio usare il filtro cors fornito di tomcat come intendi. Potresti fornirmi i passaggi? – MaatDeamon