我正在尝试编写测试以验证我们的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;
}
我已经通过调试器验证了{test}运行时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标头。
任何帮助表示感谢。
答案 0 :(得分:10)
CORS请求需要包含Origin
标头,供服务器处理。模拟GET请求没有此标头。 API允许我们在模拟请求中包含标题。
public MockHttpServletRequestBuilder header(String name, 对象...值)
为请求添加标头。始终添加值。 参数: name - 标题名称 值 - 一个或多个标题值
以下是适用的代码
.perform(options("/test-cors")
.header("Access-Control-Request-Method", "GET")
.header("Origin", "http://www.someurl.com"))
两个标头都是必需的,configuration
要求允许的来源和方法与测试中传递的值一致。
答案 1 :(得分:2)
而不是初始化CorsConfigurationSource Bean简单地直接初始化CorsFilter。只需改变这种方法并尝试,
@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!
答案 2 :(得分:0)
为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);
}
}
此外,spring boot主应用程序类包含一个 FilterRegistrationBean ,它注册CORS过滤器类。这是我主要应用课程的样本:
@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 demo app
获取更多信息答案 3 :(得分:0)
这就是我所做的。我已经使用配置@Configuration
来使用Springboot启用CORS。这是我的课程:
在applicatoin.properties文件中,您可以如下添加属性和域:
allowed.origins = .someurl.com, .otherurl.com,*。someotherurl.com
您的配置类:
@配置 @EnableWebMvc 公共类AppConfig扩展了WebMvcConfigurerAdapter {
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
。
但是,您需要在标头中传递Origin
;否则,您将从控制器中收到 403-禁止访问响应。
答案 4 :(得分:-2)
springboot 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";
}