Java Spring boot 启用全局 CORS 支持问题:只有 GET 有效,POST、PUT 和 Delete 无效
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/35315090/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring boot enable Global CORS support issue: only GET is working, POST, PUT and Delete are not working
提问by Half Ass Dev
Update: Now looking back more than a year later, I am giving an update hope that will help someone else.
更新:现在回顾一年多后,我给出了一个更新希望能帮助别人。
Spring IO recommend using CSRF protection for any request that could be processed by a browser by normal users. If you are only creating a service that is used by non-browser clients, you will likely want to disable CSRF protection. Since my app is an API and will be processed by a browser, so disable CSRF is not an approach.
Spring IO 建议对普通用户可以由浏览器处理的任何请求使用 CSRF 保护。如果您仅创建供非浏览器客户端使用的服务,您可能希望禁用 CSRF 保护。由于我的应用程序是一个 API 并且将由浏览器处理,因此禁用 CSRF 不是一种方法。
CSRF is enabled with Spring Boot by default, you would need to add the following code to add a CSRF repository and a filter to add the CSRF token to your http requests. (The solution comes from here Invalid CSRF Token in POST request)
默认情况下,Spring Boot 启用 CSRF,您需要添加以下代码以添加 CSRF 存储库和过滤器以将 CSRF 令牌添加到您的 http 请求。(解决方案来自此处Invalid CSRF Token in POST request)
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/assets/**", "/templates/**", "/custom-fonts/**", "/api/profile/**", "/h2/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.logoutSuccessUrl("/login?logout")
.permitAll()
.and()
.csrf().csrfTokenRepository(csrfTokenRepository())
.and()
.addFilterAfter(csrfHeaderFilter(), SessionManagementFilter.class); // Register csrf filter.
}
The filter & CsrfToken Repository part:
过滤器和 CsrfToken 存储库部分:
private Filter csrfHeaderFilter() {
return new OncePerRequestFilter() {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
if (csrf != null) {
Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
String token = csrf.getToken();
if (cookie == null || token != null
&& !token.equals(cookie.getValue())) {
// Token is being added to the XSRF-TOKEN cookie.
cookie = new Cookie("XSRF-TOKEN", token);
cookie.setPath("/");
response.addCookie(cookie);
}
}
filterChain.doFilter(request, response);
}
};
}
private CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setHeaderName("X-XSRF-TOKEN");
return repository;
}
Original Question I asked back in Feb 2016
我在 2016 年 2 月问过的原始问题
I working on enabeing the Global CORS support for a Spring-boot RESTful API with Spring 4.
我致力于为 Spring 4 的 Spring-boot RESTful API 提供全局 CORS 支持。
I am following the official Spring Boot Doc(https://spring.io/guides/gs/rest-service-cors/) and have added this to my Application:
我正在关注官方 Spring Boot Doc( https://spring.io/guides/gs/rest-service-cors/) 并将其添加到我的应用程序中:
public class SomeApiApplication {
public static void main(String[] args) {
SpringApplication.run(SomeApiApplication.class, args);
}
//Enable Global CORS support for the application
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:8080")
.allowedMethods("GET", "POST", "PUT", "DELETE", "HEAD")
.allowedHeaders("header1", "header2") //What is this for?
.allowCredentials(true);
}
};
}
}
I don't get why only GET is working, for the rest of http calls, I am getting an error message saying "Invalid CORS request". Do I miss anything in the set up? If my set up is not right, GET should not work as well. I am very confussed.
我不明白为什么只有 GET 正在工作,对于其余的 http 调用,我收到一条错误消息,指出“无效的 CORS 请求”。我错过了设置中的任何内容吗?如果我的设置不正确,GET 也不能正常工作。我很困惑。
回答by Krisrettiwt
I had similar issue and figured out that @CrossOrigin on my controller had to be removed to solve the problem. Yet to figure out why that is causing "Invalid CORS request".
我遇到了类似的问题,并发现必须删除控制器上的 @CrossOrigin 才能解决问题。尚未弄清楚为什么会导致“无效的 CORS 请求”。
回答by iharel
I had the same problem - GET worked. POST didn't. I looked for an answer in the CORS domain but eventually, found that it was due to CSRF protection. To solve it, I disabled CSRF protection in the security configuration:
我有同样的问题 - GET 工作。POST 没有。我在 CORS 域中寻找答案,但最终发现这是由于 CSRF 保护。为了解决这个问题,我在安全配置中禁用了 CSRF 保护:
@Configuration @EnableWebSecurity
public class SpringWebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
**.csrf().disable()** //TODO: for production, must be reconfigured in order to disable only in specific cases. This line was added because without it, HTTP POST requests did not work.
.authorizeRequests()
.antMatchers("/api/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
Make sure you understand what you're doing: https://docs.spring.io/spring-security/site/docs/current/reference/html/web-app-security.html#csrf
确保您了解自己在做什么:https: //docs.spring.io/spring-security/site/docs/current/reference/html/web-app-security.html#csrf
回答by Bruno
Try to change allowedOrigins
method to .allowedOrigins("*")
. Postman is an extension and it runs in another "host".
尝试将allowedOrigins
方法更改为.allowedOrigins("*")
. Postman 是一个扩展,它在另一个“主机”中运行。
But make sure that you understand the impacts: https://spring.io/understanding/CORS
但请确保您了解影响:https: //spring.io/understanding/CORS
回答by Charles
I had a a similar issue, only HEAD GET and POST were working for me.
I found out that addCorsMappings
has a default value for allowedMethods
.
我有一个类似的问题,只有 HEAD GET 和 POST 对我有用。我发现它addCorsMappings
有一个默认值allowedMethods
。
This code works for me:
这段代码对我有用:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
public class MyConfiguration {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedMethods("*")
.allowedOrigins("http://localhost:4200");
}
};
}
}
回答by Joginder Malik
I faced the same issue and after doing research what i found is, the browser looks for an HTTP header named Access-Control-Allow-Originin the response.
我遇到了同样的问题,在研究了我发现的问题后,浏览器在响应中查找名为Access-Control-Allow-Origin的 HTTP 标头。
The browser sends an OPTION requestto find out what methods like PUTs, DELETEare allowed. If the requested method is allowed from server side, then the browser will make the actual request, again passing or blocking the response depending on the Access-Control-Allow-Originheader in the response. Simply add a spring bean, that will solve your problem.
浏览器发送一个OPTION 请求以找出允许使用PUT、DELETE 之类的方法。如果服务器端允许请求的方法,则浏览器将发出实际请求,根据响应中的Access-Control-Allow-Origin标头再次传递或阻止响应。只需添加一个弹簧豆,即可解决您的问题。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@Configuration
public class RestConfig {
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("OPTIONS");
config.addAllowedMethod("GET");
config.addAllowedMethod("POST");
config.addAllowedMethod("PUT");
config.addAllowedMethod("DELETE");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}