2016-02-04 25 views
12

sto usando la sicurezza primavera Stivale Primavera + Jersey +, voglio avere punti finali pubblici e privati, voglio uno schema come segue:Usa percorsi diversi per le risorse pubbliche e private Jersey + avvio Primavera

  • /riposo - il mio contesto radice
  • /pubblico - voglio mettere i miei endpoint pubblici in questo contesto, deve essere all'interno del contesto radice come /rest/public/pings
  • /privato - voglio plac e le mie endpoint privati, in questo contesto, deve essere all'interno del contesto radice come /rest/private/accounts

ho la mia configurazione come segue:

Jersey configurazione: la sicurezza

@Configuration 
@ApplicationPath("/rest") 
public class RestConfig extends ResourceConfig { 
    public RestConfig() { 
     register(SampleResource.class); 
    } 
} 

Primavera configurazione:

@Configuration 
public class SecurityConfiguration extends WebSecurityConfigurerAdapter { 

........ 

    protected void configure(HttpSecurity http) throws Exception { 
     http.authorizeRequests().antMatchers("/rest/public/**").permitAll(); 
     http.antMatcher("/rest/**").authorizeRequests().anyRequest().fullyAuthenticated().and().httpBasic(); 
     http.csrf().disable(); 
    } 

} 

La domanda è: come posso registrare due percorsi di applicazione all'interno del mio contesto/resto, uno per/pubblico e l'altro per/privato?

NOTA: Ho cercato di creare un altro ResourceConfig come segue:

@Configuration 
@ApplicationPath("/rest/public") 
public class RestPublicConfig extends ResourceConfig{ 
    public RestPublicConfig() { 
     register(PingResource.class); 
    } 
} 

Ma io sto ottenendo l'errore successivo:

No qualifying bean of type [org.glassfish.jersey.server.ResourceConfig] is defined: expected single matching bean but found 2: restConfig,restPublicConfig 

Grazie per il vostro aiuto :)

risposta

0

Hai vinto Si può creare due bean per la propria classe di risorse. Puoi ottenere ciò che stai cercando di ottenere usando anche una singola classe di risorse.

Ecco un esempio:

@Path("rest") 
public class SampleResourceClass { 

    @Path("/public/pings") 
    @GET 
    public Responce getPings(){ 
    /* Code Here */ 
    } 

    @Path("/private/accounts") 
    @GET 
    public Response getAccounts(){ 
    /* Code Here */ 
    } 
} 
+0

Sì, ho capito questo, ma voglio creare molti endpoint pubblici e in questo modo posso usare solo queste classi. –

0

L'errore che state vedendo non è correlato alla propria configurazione di sicurezza, si consiglia di dare un'occhiata a questo biglietto, https://github.com/spring-projects/spring-boot/issues/3260

Se si desidera consentire tutto il traffico verso gli endpoint oltre /public è possibile aggiungere lo RequestMatcher all'elenco di ignorazioni di Spring Security.

@Configuration 
@EnableWebSecurity 
public class SecurityConfiguration extends WebSecurityConfigurerAdapter { 

    @Override 
    public void configure(WebSecurity web) throws Exception { 

     web.ignoring().antMatchers("/rest/public/**"); 
    } 

    protected void configure(HttpSecurity http) throws Exception { 

      http.authorizeRequests().antMatcher("/rest/private/**") 
      .anyRequest().authenticated().and() 
      .httpBasic().and() 
      .csrf().disable() 
    } 

} 

http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#jc

8

In un servlet container, il runtime Jersey, viene eseguito come sia un servlet o come filtro servlet. Il modo in cui spring boot configura servlet e filtri avviene tramite ServletRegistrationBean s e FilterRegistrationBeans, rispettivamente.Per avere un'idea di come funziona tale configurazione dietro le quinte, si può guardare il codice sorgente per il JerseyAutoConfiguration

Nel JerseyAutoConfiguration, si può vedere che un ResourceConfig viene iniettato, e questo è il ResourceConfig utilizzato per creare il servlet Jersey o filtro Jersey (a seconda della scelta della configurazione). Quindi la ragione dell'errore è che non puoi avere fagioli ambigui, che hai due fagioli ResourceConfig. Quindi Spring non sa quale iniettare.

Cosa si può fare, è utilizzare due servlet diversi per ogni ResourceConfig. Il problema è che Spring Boot ti aggancia solo con un servlet per Jersey, quindi devi configurare l'altro da solo. Ci sono due opzioni:

  1. utilizzare la configurazione automatica della molla di avvio per una delle applicazioni Jersey, e aggiungere un altro ServletRegistrationBean per l'altro uno. L'unica cosa da notare è che il per il tuo ServletRegistrationBean creato non dovrebbe essere un componente Spring (ad esempio, non @Component o @Configuration), altrimenti si verificherà ancora lo stesso errore.

    public class PublicConfig extends ResourceConfig { 
        public PublicConfig() { 
         register(PingResource.class); 
        } 
    } 
    ... 
    // in your Spring Boot configuration class 
    @Bean 
    public ServletRegistrationBean publicJersey() { 
        ServletRegistrationBean publicJersey 
          = new ServletRegistrationBean(new ServletContainer(new PublicConfig())); 
        publicJersey.addUrlMappings("/rest/public/*"); 
        publicJersey.setName("PublicJersey"); 
        publicJersey.setLoadOnStartup(0); 
        return publicJersey; 
    } 
    
  2. Non utilizzare affatto la configurazione Spring Boot. Basta creare due ServletRegistrationBean s. In questo caso, nessuna delle tue classi ResourceConfig deve essere Spring bean.

    @Bean 
    public ServletRegistrationBean publicJersey() { 
        ServletRegistrationBean publicJersey 
          = new ServletRegistrationBean(new ServletContainer(new PublicConfig())); 
        publicJersey.addUrlMappings("/rest/public/*"); 
        publicJersey.setName("PublicJersey"); 
        publicJersey.setLoadOnStartup(0); 
        return publicJersey; 
    } 
    
    @Bean 
    public ServletRegistrationBean privateJersey() { 
        ServletRegistrationBean privateJersey 
          = new ServletRegistrationBean(new ServletContainer(new PrivateConfig())); 
        privateJersey.addUrlMappings("/rest/private/*"); 
        privateJersey.setName("PrivateJersey"); 
        privateJersey.setLoadOnStartup(1); 
        return privateJersey; 
    } 
    

Personalmente, preferisco la seconda opzione, in quanto è più facile ragionare sulle configurazioni quando sono tutti in un unico luogo.

Un'altra cosa da notare è che le due applicazioni Jersey sarà completamente indipendente, il che significa che sarà necessario registrare i fornitori (come i filtri) sia per applicazioni

+0

Ho usato la seconda opzione, grazie mille, è stato davvero utile :) –