更新:现在回顾一年多后,我正在给出一个更新的希望,这将有助于其他人。
Spring IO 建议对普通用户可以通过浏览器处理的任何请求使用 CSRF 保护。如果您只创建由非浏览器客户端使用的服务,则可能需要禁用 CSRF 保护。由于我的应用程序是一个 API 并且将由浏览器处理,因此禁用 CSRF 不是一种方法。
默认情况下,CSRF 是使用 Spring 引导启用的,您需要添加以下代码来添加 CSRF 存储库和过滤器以将 CSRF 令牌添加到您的 http 请求中。(解决方案来自这里 POST 请求中的 CSRF 令牌无效(
@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.
}
过滤器和CsrfToken Repository部分:
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;
}
我在2016年2月问的原始问题
我致力于在Spring 4中为Spring-boot RESTful API提供全局CORS支持。
我正在遵循官方的 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);
}
};
}
}
我不明白为什么只有 GET 在工作,对于其余的 http 调用,我收到一条错误消息,指出"无效的 CORS 请求"。 我错过了设置中的任何内容吗?如果我的设置不正确,GET也不应该工作。我很困惑。
我遇到了类似的问题,只有HEAD GET和POST对我有用。我发现addCorsMappings
有一个默认值 allowedMethods
.
这段代码对我有用:
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");
}
};
}
}
我遇到了同样的问题 - GET 工作。开机自检没有。我在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();
}
确保您了解自己在做什么:https://docs.spring.io/spring-security/site/docs/current/reference/html/web-app-security.html#csrf
尝试将allowedOrigins
方法更改为.allowedOrigins("*")
。Postman 是一个扩展,它在另一个"主机"中运行。
但请确保您了解影响:https://spring.io/understanding/CORS
我遇到了同样的问题,经过研究,我发现浏览器在响应中查找名为 Access-Control-Allow-Origin 的 HTTP 标头。
浏览器发送一个选项请求,以了解允许哪些方法,如 PUT、DELETE。如果服务器端允许请求的方法,则浏览器将发出实际请求,根据响应中的访问控制允许源标头再次传递或阻止响应。只需添加一个春豆,就可以解决您的问题。
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);
}
}
我遇到了类似的问题,并发现必须删除控制器上的@CrossOrigin才能解决问题。尚未弄清楚为什么会导致"无效的 CORS 请求"。
的SecurityConfig.java
。我不得不在这篇文章中混合各种答案才能让它为我工作。
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/").permitAll();
// unblock post, put and delete requests
http.csrf().disable();
// enable cors
http.cors();
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowCredentials(true);
configuration.addAllowedOrigin("http://localhost:3000");
configuration.addAllowedHeader("*");
configuration.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
如果要允许所有源,请将http://localhost:3000
替换为*
三重检查您的路径名是否在后端/前端应用程序以及任何路径变量等之间对齐。如果合约不正确,OPTIONS 将返回 403,因为它找不到要使用的正确 API。它看起来像浏览器中的 CORS 问题,但根本原因是合同差异。