복붙노트

[SPRING] 공용 및 개인 자원에 대해 다른 경로 사용 Jersey + Spring boot

SPRING

공용 및 개인 자원에 대해 다른 경로 사용 Jersey + Spring boot

나는 스프링 부트 + 저지 + 스프링 보안을 사용하고 있으며, 공개 엔드 포인트와 개인 엔드 포인트를 갖고 싶습니다. 다음과 같이 스키마를 원합니다.

다음과 같이 구성되었습니다.

저지 구성 :

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

}

문제는 내 / 나머지 컨텍스트 내부에 두 개의 애플리케이션 경로를 등록 할 수 있다는 것입니다 (하나는 / public 용이고 다른 하나는 / private 용).

참고 : 다음과 같이 다른 ResourceConfig를 만들려고했습니다.

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

하지만 다음 오류가 발생합니다.

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

당신의 도움을 주셔서 감사합니다 :)

해결법

  1. ==============================

    1.서블릿 컨테이너에서 Jersey 런타임은 서블릿 또는 서블릿 필터로 실행됩니다. 스프링 부트가 서블릿과 필터를 구성하는 방법은 각각 ServletRegistrationBeans와 FilterRegistrationBeans를 통해 이루어집니다. 이 설정이 장면 뒤에서 어떻게 작동하는지 알기 위해 JerseyAutoConfiguration의 소스 코드를 살펴볼 수 있습니다

    서블릿 컨테이너에서 Jersey 런타임은 서블릿 또는 서블릿 필터로 실행됩니다. 스프링 부트가 서블릿과 필터를 구성하는 방법은 각각 ServletRegistrationBeans와 FilterRegistrationBeans를 통해 이루어집니다. 이 설정이 장면 뒤에서 어떻게 작동하는지 알기 위해 JerseyAutoConfiguration의 소스 코드를 살펴볼 수 있습니다

    JerseyAutoConfiguration에서 ResourceConfig가 삽입되었고, 이는 구성의 선택에 따라 Jersey 서블릿 또는 Jersey 필터를 작성하는 데 사용 된 ResourceConfig입니다. 따라서 오류의 원인은 모호한 Bean을 가질 수 없으며 두 개의 ResourceConfig Bean이 있습니다. 그래서 스프링은 어떤 것을 주입해야하는지 알지 못합니다.

    그래도 할 수있는 일은 각 ResourceConfig에 대해 두 개의 다른 서블릿을 사용하는 것입니다. 문제는 Spring Boot가 Jersey 용 서블릿 하나만 연결하므로 다른 하나를 직접 구성해야한다는 것입니다. 두 가지 옵션이 있습니다.

    개인적으로, 두 번째 옵션을 선호합니다. 구성이 모두 한 곳에서 이루어지면 구성을 추론하기가 더 쉽습니다.

    두 가지 저지 응용 프로그램은 완전히 독립적이므로 두 응용 프로그램 모두에 대해 공급자와 같은 필터를 등록해야합니다.

  2. ==============================

    2.자원 클래스에 대해 두 개의 Bean을 작성할 수 없습니다. 단일 리소스 클래스를 사용하여 달성하고자하는 것을 달성 할 수 있습니다.

    자원 클래스에 대해 두 개의 Bean을 작성할 수 없습니다. 단일 리소스 클래스를 사용하여 달성하고자하는 것을 달성 할 수 있습니다.

    다음은 그 예입니다.

    @Path("rest")
    public class SampleResourceClass {
    
      @Path("/public/pings")
      @GET
      public Responce getPings(){
        /* Code Here */
      }
    
      @Path("/private/accounts")
      @GET
      public Response getAccounts(){
        /* Code Here */
      }
    }
    
  3. ==============================

    3.표시되는 오류가 보안 설정과 관련이 없으므로 https://github.com/spring-projects/spring-boot/issues/3260에서이 티켓을 살펴 보시기 바랍니다.

    표시되는 오류가 보안 설정과 관련이 없으므로 https://github.com/spring-projects/spring-boot/issues/3260에서이 티켓을 살펴 보시기 바랍니다.

    엔드 포인트에 대한 모든 트래픽을 / public 이후에 허용하려면 RequestMatcher를 Spring Security ignore리스트에 추가하면됩니다.

    @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

  4. from https://stackoverflow.com/questions/35208439/use-different-paths-for-public-and-private-resources-jersey-spring-boot by cc-by-sa and MIT license