我需要在我的Spring Boot Web应用程序中添加CORS过滤器。
我添加了CORS映射,如以下文档中所述http://docs.spring.io/spring/docs/current/spring-framework-reference/html/cors.html
这是我的配置:
@Configuration
@EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
// @formatter:off
registry
.addMapping("/**")
.allowedOrigins(CrossOrigin.DEFAULT_ORIGINS)
.allowedHeaders(CrossOrigin.DEFAULT_ALLOWED_HEADERS)
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.maxAge(3600L);
// @formatter:on
}
...
}
现在,当我尝试访问我的API时,收到以下错误:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://example.com/api/v1.0/user. (Reason: CORS preflight channel did not succeed).
这是来自FF控制台的屏幕截图:
我做错了什么以及如何正确配置CORS标头以避免此问题?
答案 0 :(得分:41)
我已经通过创建新的CORS过滤器解决了这个问题:
@Component
public class CorsFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "authorization, content-type, xsrf-token");
response.addHeader("Access-Control-Expose-Headers", "xsrf-token");
if ("OPTIONS".equals(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
filterChain.doFilter(request, response);
}
}
}
并将其添加到securty配置中:
.addFilterBefore(new CorsFilter(), ChannelProcessingFilter.class)
更新 - 我现在更加现代化的方式:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors()
.and()
...
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"));
configuration.setAllowedHeaders(Arrays.asList("authorization", "content-type", "x-auth-token"));
configuration.setExposedHeaders(Arrays.asList("x-auth-token"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
答案 1 :(得分:6)
如果让CORS与spring数据休息一起工作有同样的问题,这就是我使用的过滤器代码。
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>
void main()
{
char *words[] = {"sausage","blubber","pencil","cloud","moon","water","computer","school","network","hammer","walking","violently","mediocre","literature","chair","two","window","cords","musical","zebra","xylophone","penguin","home","dog","final","ink","teacher","fun","website","banana","uncle","softly","mega","ten","awesome","attatch","blue","internet","bottle","tight","zone","tomato","prison","hydro","cleaning","telivision","send","frog","cup","book","zooming","falling","evily","gamer","lid","juice","moniter","captain","bonding","loudly","thudding","guitar","shaving","hair","soccer","water","racket","table","late","media","desktop","flipper","club","flying","smooth","monster","purple","guardian","bold","hyperlink","presentation","world","national","comment","element","magic","lion","sand","crust","toast","jam","hunter","forest","foraging","silently","tawesomated","joshing","pong","RANDOM","WORD"};
char *questions[] = {"sausage1","blubber1","pencil1","cloud1","moon1","water1","computer1","school1","network1","hammer1","walking1","violently1","mediocre1","literature1","chair1","two1","window1","cords1","musical1","zebra1","xylophone1","penguin1","home1","dog1","final1","ink1","teacher1","fun1","website1","banana1","uncle1","softly1","mega1","ten1","awesome1","attatch1","blue1","internet1","bottle1","tight1","zone1","tomato1","prison1","hydro1","cleaning1","telivision1","send1","frog1","cup1","book1","zooming1","falling1","evily1","gamer1","lid1","juice1","moniter1","captain1","bonding1","loudly1","thudding1","guitar1","shaving1","hair1","soccer1","water1","racket1","table1","late1","media1","desktop1","flipper1","club1","flying1","smooth1","monster1","purple1","guardian1","bold1","hyperlink1","presentation1","world1","national1","comment1","element1","magic1","lion1","sand1","crust1","toast1","jam1","hunter1","forest1","foraging1","silently1","tawesomated1","joshing1","pong1","RANDOM1","WORD1"};
char answer[255] = "";
int word;
int vec[20] = { 0 };
int i, j;
int x=0;
srand(time(NULL));
do{
for (i = 0; i < 20; i++) {
int okay = 0;
while (!okay) {
vec[i] = rand() % 100 + 1;
okay = 1;
for (j = 0; j < i; j++) {
if (vec[i] == vec[j]) okay = 0;
}
}
word=vec[i];
printf("%s\n",questions[word]); //print a word
scanf("%255s",answer);// wait for the user to type the word
printf("%s\n",answer[x]);// show what the user typed
printf("%s\n\n",words[word]);// show how they should of typed it
}
}while (x<20,x++);
return 0;
}
答案 2 :(得分:4)
按照以下两个教程操作,我仍然遇到CORS错误:
首先,我遵循网络安全指南:https://spring.io/guides/gs/securing-web/#scratch
第二,我遵循了CORS指南:https://spring.io/guides/gs/rest-service-cors/#global-cors-configuration
要按照这些指南解决问题,我必须在http安全性中添加http.cors()
。
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors()
.and()
...
}
添加.cors()
使其可以使用我为CORS配置声明的@Bean
。
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("http://localhost:4200");
}
};
}
答案 3 :(得分:2)
为了它的价值,以下组合解决方案对我有用:
1
@Configuration
public class CorsConfiguration {
//This can be used in combination with @CrossOrigin on the controller & method.
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedMethods("HEAD","OPTIONS")
.allowedHeaders("Origin", "X-Requested-With", "Content-Type", "Accept");
}
};
}
}
2。 RestController类上的@CrossOrigin
。让@CrossOrigin
读取@RequestMapping
注释及其中的HTTP方法。其余请求因CORS错误而被拒绝。
但如果您想在项目中使用spring security,那么您将无法使用上述解决方案。
我使用的是春季启动版1.5.4.RELEASE。
答案 4 :(得分:1)
这非常简单并且运行良好。在您为Web安全配置编写的类中,输入以下行httpSecury.cors();
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.cors(); // This enables cors
// Your codes
}
}
答案 5 :(得分:1)
第1步:在控制器中添加此注释
@CrossOrigin
public class JobController {}
Step2:将其添加到您的任何配置中
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*");
}
};
}
这仅在您的控制器上具有@CrossOrigin注释时才有效
答案 6 :(得分:1)
如果您在 Spring Security 中使用 CORS,这是最新的文档:https://docs.spring.io/spring-security/site/docs/current/reference/html5/#cors
这类似于本页其他地方引用的代码:
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// by default uses a Bean by the name of corsConfigurationSource
.cors(withDefaults())
...
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("https://example.com"));
configuration.setAllowedMethods(Arrays.asList("GET","POST"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
尽管您可以在其他地方配置 CORS,但将其作为安全配置的一部分是有意义的,因为它们紧密相关,因为 CORS 处理必须在安全处理之前进行 - 之前的帖子已经指出.上面引用的文档中给出的原因是:
"CORS 必须在 Spring Security 之前处理,因为 pre-flight 请求不会包含任何 cookie(即 JSESSIONID)。如果请求不包含任何 cookie 并且 Spring Security 是第一个,请求将确定用户不是已通过身份验证(因为请求中没有 cookie)并拒绝它。”
在 http 配置的开头添加 .cors() 行 - 如上所示 - 可以实现。否则,飞行前 OPTIONS 请求将得不到响应。
答案 7 :(得分:0)
正确处理飞行前OPTIONS请求是必要的,但跨站点资源请求无法正常工作。
在OPTIONS请求返回满意的标题后,对同一URL的任何后续请求的所有响应也必须具有必要的&#34; Access-Control-Allow-Origin&#34;标题,否则浏览器将吞下它们,它们甚至不会出现在调试器窗口中。 https://stackoverflow.com/a/11951532/5649869
答案 8 :(得分:0)
目前推荐的做CORS的方法是
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://domain2.com")
.allowedMethods("PUT", "DELETE")
.allowedHeaders("header1", "header2", "header3")
.exposedHeaders("header1", "header2")
.allowCredentials(true).maxAge(3600);
// Add more mappings...
}
}
这基于https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-cors
但您还需要确保在WebSecurityConfig文件中启用了CORS并禁用了CSRF。
我曾经遇到过一个问题,我的所有POST方法都没有工作(返回403 forbiden),而GET方法工作得很好,但这在CSRF被禁用后解决了
答案 9 :(得分:0)
如果使用下面的代码使用spring-boot 2足以解决cors问题和预检问题
@Override
public void configure(WebSecurity web) throws Exception {
// web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
web.ignoring().antMatchers("/resources/**", "/index.html", "/login.html", "/partials/**", "/template/**", "/",
"/error/**", "/h2-console", "*/h2-console/*");
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration config = new CorsConfiguration();
config.applyPermitDefaultValues();
config.setAllowCredentials(true);// this line is important it sends only specified domain instead of *
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return source;
}
答案 10 :(得分:0)
这对我有用
@Configuration
public class CorsConfig implements WebMvcConfigurer {
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS");
}
}
答案 11 :(得分:0)
这是我用于 Cors 配置以与 Spring Boot 配合使用的一段代码。这是主应用程序类中的 corsFilter 配置。
应用程序正在'http://localhost:4200'上运行
import org.springframework.context.annotation.Bean;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import java.util.Arrays;
@Bean
public CorsFilter corsFilter() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowCredentials(true);
corsConfiguration.setAllowedOrigins(Arrays.asList("http://localhost:4200"));
corsConfiguration.setAllowedHeaders(Arrays.asList("Origin", "Access-Control-Allow-Origin", "Content-Type",
"Accept", "Authorization", "Origin, Accept", "X-Requested-With",
"Access-Control-Request-Method", "Access-Control-Request-Headers"));
corsConfiguration.setExposedHeaders(Arrays.asList("Origin", "Content-Type", "Accept", "Authorization",
"Access-Control-Allow-Origin", "Access-Control-Allow-Origin", "Access-Control-Allow-Credentials"));
corsConfiguration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
return new CorsFilter(urlBasedCorsConfigurationSource);
}
答案 12 :(得分:0)
AFAIK,对于所有 http 请求,都会向服务器发送预检请求,以检查该特定 api 请求的访问权限。预检请求通常是一个“OPTION”http 请求,它发送即将到来的请求所需的元数据。
所以错误,预检通道没有成功意味着发送到服务器的预检请求被阻止或拒绝。 在大多数情况下,这是因为
从Spring security 5.4.5开始,我们基本上可以通过上面提到的几点来检查这是否是潜在的问题。
创建或更新扩展 WebMvcConfigurer
的类@Override
public void addCorsMappings(CorsRegistry registry) {
//The pattern, allowedOrigins and allowedMethods should be restricted to the frontend application url,
//so that CORS attacks won't happen
registry.addMapping("/**").allowedOrigins("*").allowedMethods("*");
}
这里,addMapping 带有“API 端点”的参数,我们提供“*”来配置服务器支持的所有端点。
allowedOrigins 对应于我们上面提供的映射支持的 UI 应用程序路径 (*)
allowedMethods 接受您的服务器允许的所有 http 方法的数组。
在生产环境中,我们提供的此配置应限制为适当的值。
此外,在扩展 WebSecurityConfigurerAdapter
的配置类中@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors()
.and()
.......
.authenticated();
}
注意我们提供的“http.cors()”方法