使用不同的路径为公共和私人资源Jersey + Spring启动

时间:2016-02-04 18:09:20

标签: java spring rest spring-boot jersey

我正在使用Spring boot + Jersey + Spring安全性,我想拥有公共和私有端点,我想要一个架构如下:

  • / rest - 我的根上下文
  • / public - 我希望将公共端点放在此上下文中,它必须位于根{2}}
  • 之类的根上下文中
  • / private - 我希望将我的私有端点放在此上下文中,它必须位于根{2}}
  • 之类的根上下文中

我的配置如下:

泽西配置:

/rest/public/pings

Spring security 配置:

/rest/private/accounts

问题是如何在my / rest上下文中注册两个应用程序路径,一个用于/ public,另一个用于/ private?

注意:我尝试创建另一个ResourceConfig,如下所示:

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

但是我收到了下一个错误:

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

}

感谢您的帮助:)

3 个答案:

答案 0 :(得分:11)

在servlet容器中,Jersey运行时作为servlet或servlet过滤器运行。 Spring引导如何配置servlet和过滤器分别是ServletRegistrationBeanFilterRegistrationBeans。要了解该配置如何在幕后工作,您可以查看JerseyAutoConfiguration

的源代码

JerseyAutoConfiguration中,您可以看到注入ResourceConfig,这是用于创建Jersey servlet或Jersey过滤器的ResourceConfig(取决于您选择的配置) 。所以错误的原因是你不能有不明确的bean,你有两个ResourceConfig bean。所以Spring并不知道要注射哪一个。

问题是Spring Boot只为你提供了一个针对Jersey的servlet,所以你需要自己配置另一个。有两种选择:

  1. 对其中一个Jersey应用程序使用Spring Boot自动配置,并为另一个应用程序添加另一个ResourceConfig。需要注意的一点是,您创建的ServletRegistrationBean的{​​{1}}不应该是Spring组件(即没有ResourceConfigServletRegistrationBean),否则您仍将面临同样的错误。

    @Component
  2. 根本不使用Spring Boot配置。只需创建两个@Configuration。在这种情况下,您的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; } 类都不应该是Spring bean。

    ServletRegistrationBean
  3. 就个人而言,我更喜欢第二种选择,因为当它们都在一个地方时,更容易推断配置。

    另外需要注意的是,两个Jersey应用程序将完全独立,这意味着您需要为两个应用程序注册提供程序(如过滤器)

答案 1 :(得分:0)

您不会被允许为您的资源类创建两个bean。您也可以使用单个资源类来实现您想要实现的目标。

以下是一个例子:

@Path("rest")
public class SampleResourceClass {

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

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

答案 2 :(得分:0)

您看到的错误与您的安全配置无关,您可能需要查看此故障单,https://github.com/spring-projects/spring-boot/issues/3260

如果要允许所有流量到/public之后的端点,可以将RequestMatcher添加到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