programing

Spring Boot에서의 COR 테스트시험

bestprogram 2023. 4. 2. 12:01

Spring Boot에서의 COR 테스트시험

나는 우리의 CORS 설정을 확인하기 위한 테스트를 작성하려고 합니다.CORS는 이렇게 설정합니다.

@Override
    public void configure(HttpSecurity httpSecurity) throws Exception {
//        super.configure(httpSecurity);
        httpSecurity.csrf().disable();
        httpSecurity.authorizeRequests().antMatchers("/**").permitAll();
        httpSecurity.cors();
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        List<String> allowedMethods = CORS_ALLOWED_METHODS;
        configuration.setAllowedMethods(allowedMethods);
        configuration.setAllowedOrigins(CORS_ALLOWED_ORIGINS);
        configuration.setAllowedHeaders(CORS_ALLOWED_HEADERS);
        configuration.setAllowCredentials(true);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

디버거를 사용하여 확인했습니다.CORS_ALLOWED_METHODS테스트 실행 시 값이 표시됩니다.

이게 제 시험이에요.헤더에 어설트 하면 실패합니다.

@RunWith(SpringRunner.class)
@SpringBootTest
@ActiveProfiles("dev")
public class ControllerTests {

    @Autowired
    private WebApplicationContext wac;

    public MockMvc mockMvc;

    @Before
    public void setup() {
        DefaultMockMvcBuilder builder = MockMvcBuilders
                .webAppContextSetup(this.wac)
                .apply(SecurityMockMvcConfigurers.springSecurity())
                .dispatchOptions(true);
        this.mockMvc = builder.build();
    }

    @Test
    public void testCors() throws Exception {
        this.mockMvc
                .perform(get("/test-cors"))
                .andDo(print())
                .andExpect(status().isOk())
                .andExpect(header().string("Access-Control-Allow-Methods", "OPTIONS,GET,HEAD,POST,PUT,DELETE,TRACE,CONNECT"))
                .andExpect(content().string("whatever"));
    }

    @SpringBootApplication(scanBasePackages = {"the.packages"})
    @Controller
    static class TestApplication {

        public static void main(String[] args) throws Exception {
            SpringApplication.run(TestApplication.class, args);
        }

        @RequestMapping(value = {"test-cors"},  method = RequestMethod.GET)
        @ResponseStatus(HttpStatus.OK)
        public @ResponseBody String testCors() {
            return "whatever";
        }
    }
}

참고로 이 구성으로 실제로 SpringBoot 앱을 실행하면 CORS 헤더가 표시됩니다.

아무쪼록 잘 부탁드립니다.

CORS 요청에는 다음 사항을 포함해야 합니다.Originheader를 지정합니다.모의 GET 요청에는 이 헤더가 없습니다.API를 사용하면 모의 요청에 헤더를 포함할 수 있습니다.

public MockHttpServletRequestBuilder 헤더(문자열 이름, 객체...)값)

요청에 헤더를 추가합니다.값은 항상 추가됩니다.파라미터: name - 헤더 이름 값 - 1개 이상의 헤더 값

여기 동작하는 코드가 있습니다.

.perform(options("/test-cors")
    .header("Access-Control-Request-Method", "GET")
    .header("Origin", "http://www.someurl.com"))

양쪽 헤더가 필요하며,configuration에서는 허용되는 원점 및 방법이 테스트에서 전달된 값과 일치해야 합니다.

Cors Configuration Source Bean을 초기화하지 않고 Cors Filter를 바로 초기화합니다.그 방법을 이렇게 바꿔서 시도해 보세요.

@Bean
public CorsFilter corsFilter() {
        CorsConfiguration configuration = new CorsConfiguration();
        List<String> allowedMethods = CORS_ALLOWED_METHODS;
        configuration.setAllowedMethods(allowedMethods);
        configuration.setAllowedOrigins(CORS_ALLOWED_ORIGINS);
        configuration.setAllowedHeaders(CORS_ALLOWED_HEADERS);
        configuration.setAllowCredentials(true);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return new CorsFilter(source);
}

HTH!

CORS 설정 테스트를 작성하는 또 다른 방법은 사전 정의된 URL에서 모의 요청을 수행한 후 MockHttpServletResponse를 아사트하는 것입니다.나에게 유효한 코드는 다음과 같습니다.

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
@ActiveProfiles("corsFilterBean")
public class CORSFilterTests {

@Autowired
private MockMvc mvc;

@Test
public void test_corsFilterBean() throws Exception {

    MvcResult result = mvc
            .perform(get("/users/all"))
            .andExpect(status().isOk())
            .andExpect(header().string("Access-Control-Allow-Origin", "*"))
            .andExpect(header().string("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE"))
            .andExpect(header().string("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, X-Auth-Token, X-Csrf-Token, WWW-Authenticate, Authorization"))
            .andExpect(header().string("Access-Control-Expose-Headers", "custom-token1, custom-token2"))
            .andExpect(header().string("Access-Control-Allow-Credentials", "false"))
            .andExpect(header().string("Access-Control-Max-Age", "3600"))
            .andDo(print())
            .andReturn();

    MockHttpServletResponse mockResponse = result.getResponse();

    assertThat(mockResponse.getContentType()).contains("application/json;charset=UTF-8");

    Collection<String> responseHeaders = mockResponse.getHeaderNames();
    assertThat(responseHeaders).isNotNull();
    assertThat(1).isEqualTo(1);
    assertThat(responseHeaders.size()).isBetween(5, 15);
  }
}

이것은, 크로스 오리진 요구를 유효하게 하는 CORS 사양 클래스가 있는 것을 전제로 하고 있습니다.다음은 CORS 필터 클래스의 예입니다.

public class CORSFilterss extends GenericFilterBean implements Filter {

private Logger logger = LoggerFactory.getLogger(this.getClass());

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {

    HttpServletResponse httpResponse = (HttpServletResponse) response;
    httpResponse.setHeader("Access-Control-Allow-Origin", "*");
    httpResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
    httpResponse.setHeader("Access-Control-Allow-Headers",
            "Origin, X-Requested-With, Content-Type, Accept, X-Auth-Token, X-Csrf-Token, WWW-Authenticate, Authorization");
    httpResponse.setHeader("Access-Control-Expose-Headers", "custom-token1, custom-token2");
    httpResponse.setHeader("Access-Control-Allow-Credentials", "false");
    httpResponse.setHeader("Access-Control-Max-Age", "3600");

    StringBuilder sb = new StringBuilder();
    sb.append("\nCORS HEADERS:\n");
    sb.append("---------------\n");
    httpResponse.getHeaderNames()
            .forEach(name -> {
                        sb.append(name).append(": ").append(httpResponse.getHeader(name)).append("\n");
                    }
            );
    logger.debug("********** CORS Configuration Completed **********");
    logger.debug(sb.toString());

    chain.doFilter(request, response);
  }
} 

또한 스프링 부트메인 어플리케이션클래스에는 CORS 필터 클래스를 등록하는 FilterRegistrationBean이 포함되어 있습니다.다음은 주요 응용 프로그램 클래스의 예입니다.

@SpringBootApplication
public class SpringTestingApplication implements CommandLineRunner {

public static void main(String[] args) {
    SpringApplication.run(SpringTestingApplication.class, args);
}
@Override
public void run(String... args) throws Exception {

}
@Bean
public FilterRegistrationBean corsFilterRegistration() {
    FilterRegistrationBean registrationBean =
            new FilterRegistrationBean(new CORSFilterss());
    registrationBean.setName("CORS FILTER");
    registrationBean.addUrlPatterns("/*");
    registrationBean.setOrder(1);

    return registrationBean;

  }
}

github 데모 앱에서 더 많은 정보를 얻을 수 있습니다.

이게 내가 한 일이야.설정을 사용한 적이 있다@ConfigurationSpringboot를 사용하여 CORS를 활성화합니다.제 수업은 다음과 같습니다.

applicationatoin.properties 파일에서 다음과 같이 속성과 도메인을 추가할 수 있습니다.

allowed.webooks=.someurl.com, .someotherurl.com, *.someotherurl.com

또한 구성 클래스:

@Configuration @EnableWebMvc 퍼블릭 클래스 AppConfig는 WebMvcConfigrAdapter {를 확장합니다.

private static final Logger logger = LoggerFactory.getLogger(AppConfig.class);

@Value("#{'${allowed.origins}'.split(',')}")
private List<String> rawOrigins;

@Bean
public RestTemplate restTemplate() {
    return new RestTemplate();
}

@Bean
public WebMvcConfigurer corsConfigurer() {
    return new WebMvcConfigurerAdapter() {
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            logger.info("Adding CORS to the APP");
            registry.addMapping("/**")
                        .allowedOrigins(getOrigin())
                    .allowedMethods(HttpMethod.GET.name(), HttpMethod.POST.name(), HttpMethod.OPTIONS.name())
                    .allowedHeaders(HttpHeaders.AUTHORIZATION, HttpHeaders.CONTENT_TYPE, "accessToken", "CorrelationId", "source")
                    .exposedHeaders(HttpHeaders.AUTHORIZATION, HttpHeaders.CONTENT_TYPE, "accessToken", "CorrelationId", "source")
                    .maxAge(4800);
        }
        /**
         * This is to add Swagger to work when CORS is enabled
         */
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {

               registry.addResourceHandler("swagger-ui.html")
                        .addResourceLocations("classpath:/META-INF/resources/");

                registry.addResourceHandler("/webjars/**")
                        .addResourceLocations("classpath:/META-INF/resources/webjars/");

        }
    };
}


public String[] getOrigin() {
    int size = rawOrigins.size();
    String[] originArray = new String[size];
    return rawOrigins.toArray(originArray);
}

}

컨트롤러 테스트클래스는 다음과 같습니다.

@RunWith(SpringRunner.class)
@WebMvcTest(AuthController.class)
@AutoConfigureMockMvc(secure=false)
@SuppressWarnings("unchecked")
public class AuthControllerTest {

public static final String EXPIRES_IN = "expiresIn";
public static final String TOKEN_TYPE = "tokenType";
public static final String SCOPE = "scope";
public static final String ID_TOKEN = "idToken";
@Autowired
private MockMvc mockMvc;

@MockBean
private AuthService service;

@Mock
private WebMvcConfigurer corsConfigurer;

private static final ObjectMapper objectMapper = new ObjectMapper();

private static final String RESPONSE_JSON = "{\"response\":\"result\"}";

private static final String REDIRECT_URL = "url";

private static final String CODE = "code";

private static final String STATE = "state";

private static final String ACCESS_TOKEN = "accessToken";

private static final Map<String, String> requestHeaders = new HashMap<>();

@Before
public void setup() {
        requestHeaders.put("source", "source");
        requestHeaders.put("CorrelationId", "CorrelationId");
}

/**
* Controller Test to pass the CORS
*/
@Test
public void testGetLoginUrl() throws Exception {
    when(service.getLoginUrl(anyString(),anyMap())).thenReturn(objectMapper.readTree(RESPONSE_JSON));
    this.mockMvc.perform(get("/vendor/auth/loginurl?redirect_url="+ REDIRECT_URL)
            .header("CorrelationId", "1234")
            .header("Origin", "http://localhost:8080"))
            .andDo(print())
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.response", is("result")));

}
}

참고로, 테스트 수업에서,WebMvcConfigurer이 경우 내부적으로는CORS Registry.SpringTest

ㅇㅇㅇㅇㅇㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴ.Origin403 - 컨트롤러로부터의 금지 응답을 얻을 수 있습니다.

스프링 부트 2.0

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
@EnableWebMvc
public class CorsConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowCredentials(true)
                .allowedMethods("*")
                .maxAge(3600);
    }

또는

@CrossOrigin(origins="http://localhost:9000", maxAge=3600)
@RestController
public class RestController {}

또는

@CrossOrigin(origins="http://localhost:9000")
@GetMapping("/hello")
public Greeting greeting() {
    return "world";
}

언급URL : https://stackoverflow.com/questions/42588692/testing-cors-in-springboottest