I'm using Spring boot + Jersey + Spring security, I want to have public and private endpoints, I want an schema as follow:
- /rest -- My root context
- /public -- I want to place my public endpoints in this context, It must be inside of the root context like
/rest/public/pings
- /private -- I want to place my private endpoints in this context, It must be inside of the root context like
/rest/private/accounts
I have my configuration as follow:
Jersey configuration:
@Configuration
@ApplicationPath("/rest")
public class RestConfig extends ResourceConfig {
public RestConfig() {
register(SampleResource.class);
}
}
Spring security configuration:
@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();
}
}
The question is how can I register two application paths inside of my /rest context, one for /public and the other one for /private ?
NOTE: I tried to create another ResourceConfig as follow:
@Configuration
@ApplicationPath("/rest/public")
public class RestPublicConfig extends ResourceConfig{
public RestPublicConfig() {
register(PingResource.class);
}
}
But I'm getting the next error:
No qualifying bean of type [org.glassfish.jersey.server.ResourceConfig] is defined: expected single matching bean but found 2: restConfig,restPublicConfig
Thanks for your help :)
The error you are seeing is not related to your security config, you may want to take a look at this ticket, https://github.com/spring-projects/spring-boot/issues/3260
If you want to permit all traffic to endpoints past
/public
you can add theRequestMatcher
to the Spring Security ignore list.http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#jc
You won't be allowed to create two beans for your Resource Class. You can achieve what you are trying to achieve using a single Resource Class as well.
Here is an example:
In a servlet container, the Jersey runtime, runs as either a servlet or as a servlet filter. How spring boot configures servlets and filters is through
ServletRegistrationBean
s andFilterRegistrationBeans
, respectively. To get an idea of how that configuration works behind scenes, you can look at the source code for theJerseyAutoConfiguration
In the
JerseyAutoConfiguration
, you can see that aResourceConfig
is injected, and that is theResourceConfig
used to create the Jersey servlet or Jersey filter (depending on your choice of configuration). So the reason for the error is that you can't have ambiguous beans, which you have twoResourceConfig
beans. So Spring doesn't know which one to inject.What you can do though, is use two different servlets for each
ResourceConfig
. The problem is that Spring Boot only hooks you up with one servlet for Jersey, so you need to configure the other one yourself. There are two options:Use the Spring Boot auto-configuration for one of the Jersey applications, and add another
ServletRegistrationBean
for your other one. The one thing to note is that theResourceConfig
for your createdServletRegistrationBean
should not be a Spring component (i.e. no@Component
or@Configuration
), or else you will still face the same error.Don't use the Spring Boot configuration at all. Just create two
ServletRegistrationBean
s. In this case, none of yourResourceConfig
classes should be Spring beans.Personally, I prefer the second option, as it is easier to reason about the configurations when they are all in one place.
Another thing to note is that the two Jersey applications will be completely independent, meaning you will need to register providers (like filters) for both applications