我正在使用Spring boot + Jersey + Spring安全性,我想拥有公共和私有端点,我想要一个架构如下:
我的配置如下:
泽西配置:
/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();
}
}
感谢您的帮助:)
答案 0 :(得分:11)
在servlet容器中,Jersey运行时作为servlet或servlet过滤器运行。 Spring引导如何配置servlet和过滤器分别是ServletRegistrationBean
和FilterRegistrationBeans
。要了解该配置如何在幕后工作,您可以查看JerseyAutoConfiguration
在JerseyAutoConfiguration
中,您可以看到注入ResourceConfig
,这是用于创建Jersey servlet或Jersey过滤器的ResourceConfig
(取决于您选择的配置) 。所以错误的原因是你不能有不明确的bean,你有两个ResourceConfig
bean。所以Spring并不知道要注射哪一个。
问题是Spring Boot只为你提供了一个针对Jersey的servlet,所以你需要自己配置另一个。有两种选择:
对其中一个Jersey应用程序使用Spring Boot自动配置,并为另一个应用程序添加另一个ResourceConfig
。需要注意的一点是,您创建的ServletRegistrationBean
的{{1}}不应该是Spring组件(即没有ResourceConfig
或ServletRegistrationBean
),否则您仍将面临同样的错误。
@Component
根本不使用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
就个人而言,我更喜欢第二种选择,因为当它们都在一个地方时,更容易推断配置。
另外需要注意的是,两个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