我读了StackOverflow上关于这个主题的所有帖子,但没有找到答案,因为它们都是关于不同的场景比我的。
我的spring Boot API使用Spring Security并通过Angular客户端访问。
Angular客户端可以查询各种端点,我的API使用CorsConfiguration
setAllowedOrigins
方法将“Access-Control-Allow-Origin
“添加为“http://localhost:4200”。
但是,其中一个端点调用另一个API。该API也将其自己的“Access-Control-Allow-Origin
“设置为“"。
如果我的客户端查询此终结点,则会出现以下错误:
“**CORS政策:“Access-Control-Allow-Origin”标头包含多个值“http://localhost:4200,”,但只允许一个值。**”
因此,第二个API添加了带有 * 的头,然后我的API也添加了“http://localhost:4200”,最后在Access-Control-Allow-Origin
头中得到了两个条目,如“http://localhost:4200,*"。
我想解决这个问题,但我不知道如何解决。
我的API安全配置正在添加如下CorsConfiguration:
@Configuration
@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.authenticationProvider(...);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.
cors()
.and()
.csrf().disable()
.and()
.anyRequest()
.authenticated()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
final CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("http://localhost:4200"));
configuration.setAllowedMethods(Arrays.asList("*"));
configuration.setAllowCredentials(true);
configuration.setAllowedHeaders(Arrays.asList("*"));
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
我所有的控制器都标注了:
@CrossOrigin(origins = "http://localhost:4200")
上面,我调用setAllowedOrigins(Arrays.asList("http://localhost:4200"))
来设置API中的“Access-Control-Allow-Origin”头。
我的API中的所有端点都按预期工作,只有一个端点调用了另一个API。该API还将“Access-Control-Allow-Origin”设置为“”,然后返回到我的API中,导致双精度值:“访问控制允许来源”中的“http://localhost:4200”和“”。
这是我的控制器和服务失败了。如前所述,所有其他的(不调用另一个API)都工作正常。
下面是我的控制器,它调用我下面提供的服务。服务调用成功并返回响应。但是,一旦这个响应发送到客户端,我得到上面的错误。
@RestController
@RequestMapping("/wagen")
@CrossOrigin(origins = "http://localhost:4200")
public class WagenController {
public WagenController(WagenService service) {
wagenService = service;
}
@PostMapping
public ResponseEntity<WagenResponse> getWagen(@RequestBody WagenRequest wagenRequest, @RequestHeader HttpHeaders httpHeaders, HttpServletResponse response) {
ResponseEntity<WagenResponse> wagenResponse = wagenService.getWagen(wagenRequest, httpHeaders);
return wagenResponse;
}
}
下面是我的服务。它使用restTemplate调用其他API。所有这些工作正常:
@Override
public ResponseEntity<WagenResponse> getWagen(WagenRequest wagenRequest, HttpHeaders httpHeaders) {
List<String> authHeader = httpHeaders.get("authorization");
HttpHeaders headers = new HttpHeaders();
// add BasicAuth for the other API before calling it in
// below restTemplate call
headers.add("Authorization", authHeader.get(0));
HttpEntity<WagenRequest> request = new HttpEntity<WagenRequest>(wagenRequest, headers);
ResponseEntity<WagenResponse> wagenResponse = restTemplate.postForEntity(uri, request, WagenResponse.class);
return wagenResponse;
}
我如何解决这个问题,使我没有第二个条目在'访问控制-允许-起源'?或一些其他方法?
我没有办法更改其他API发送给我的内容。
下面是开发工具中网络标签的屏幕截图和控制台中显示的错误(这在PostMan中运行良好)。有趣的是,Firefox开发工具显示:
2条答案
按热度按时间wdebmtf21#
问题在于如何调用作为额外CORS标头源的其他API。
在端点中,调用
getWagen
并检索ResponseEntity
作为响应:问题在于如何处理来自Wagen API的响应。
ResponseEntity
是来自另一个API的“全部”响应--包括标头。如果在return
语句上放置一个断点,您将能够浏览wagenResponse
对象,并看到标头包括由另一个API返回的"*"
CORS标头。通过按原样返回
ResponseEntity
,您将同时返回这些API标头。然后,您应用中的装饰器和注解将在Wagen API返回的标头 * 之上 * 添加CORS标头...这就是问题所在。从
getWagen
方法返回ResponseEntity<WagenResponse>
时,需要挑选出实际需要的位--正文、状态、任何非CORS头--然后生成一个 newResponseEntity
返回给调用者。ccgok5k52#
我是Java Sping Boot 的新手,但我是这样处理CORS的:在main()下:
希望能帮到你!