弹簧CORS错误

Posted

技术标签:

【中文标题】弹簧CORS错误【英文标题】:Spring CORS error 【发布时间】:2017-12-31 19:27:27 【问题描述】:

我正在使用 Spring 构建 WebApi,并使用 Reactjs 构建客户端。我正在尝试针对 WebApi 执行 POST 请求以使用 OAuth2 进行身份验证,但我不断收到

预检响应包含无效的 HTTP 状态代码 401

WebSecurityConfigurerAdapter:

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter 

    @Bean
    public CorsFilter corsFilter() 
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(false); //updated to false
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("GET");
        config.addAllowedMethod("PUT");
        config.addAllowedMethod("POST");
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http
                .csrf().disable()
                .exceptionHandling()
                .authenticationEntryPoint((request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED))
                .and()
                .authorizeRequests()
                .antMatchers(HttpMethod.OPTIONS).permitAll()
                .antMatchers("/**").authenticated()
                .and()
                .httpBasic();
    

我的要求是:

fetch( 
      this.getAuthEndpoint('password'), 
        method:'post',
      headers: 
        'Access-Control-Allow-Origin': '*', 
        'Authorization': 'Basic dG9ucjpzZWNyZXQ='
      ,
      body: JSON.stringify(
        'password': credentials.password,
        'username': credentials.username,
        'grant_type': 'password',
        'scope': 'read write',
        'client_secret': Config.clientSecret,
        'client_id': Config.clientId
      ))
      .then(response => 
        this.saveTokens(response.data);

        return axios.get(Config.apiUrl + '/me');
      )
      .then(response => 
        this.loginSuccess(response.data.user);
      )
      .catch(response => 
        this.loginError(response);
      );

请求/响应状态为:

【问题讨论】:

【参考方案1】:

尝试做 http.cors().. 像

@Override
protected void configure(HttpSecurity http) throws Exception 
    http.cors()....

参考https://spring.io/blog/2015/06/08/cors-support-in-spring-framework

这将添加一个 CORS 过滤器并立即返回,而不是将请求传递给安全过滤器。

【讨论】:

【参考方案2】:

如果您使用的是 Springboot,请将以下代码添加到 application.java 中

  package com.khan.vaquar;

import java.util.Arrays;
import java.util.Collections;
import java.util.stream.Collectors;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@SpringBootApplication
public class SpringBootGraphqlApplication 

    public static void main(String[] args) 
        SpringApplication.run(SpringBootGraphqlApplication.class, args);
    

    @Bean
    public CorsFilter corsFilter() 
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        final CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.setAllowedOrigins(Collections.singletonList("*"));
        config.setAllowedHeaders(Collections.singletonList("*"));
        config.setAllowedMethods(Arrays.stream(HttpMethod.values()).map(HttpMethod::name).collect(Collectors.toList()));
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    

【讨论】:

【参考方案3】:

添加一个 CorsFilter

@Component    
@Order(Ordered.HIGHEST_PRECEDENCE)    
public class SimpleCorsFilter implements Filter 

//private final Logger log = LoggerFactory.getLogger(SimpleCorsFilter.class);
    public SimpleCorsFilter() 
        System.out.println("SimpleCORSFilter init");
    

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException 

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me, Authorization, x-auth-token");

        System.out.println("cors filter called");
        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) 
         response.setStatus(HttpServletResponse.SC_OK);
        else 
            chain.doFilter(req, res);
       
    // chain.doFilter(req, res);
    

    @Override
    public void init(FilterConfig filterConfig) 
    

    @Override
    public void destroy() 
    


【讨论】:

以上是关于弹簧CORS错误的主要内容,如果未能解决你的问题,请参考以下文章

弹簧安全CORS过滤器

弹簧安全CORS过滤器

弹簧安全CORS过滤器

弹簧安全CORS过滤器

keycloak CORS 过滤器弹簧靴

添加@CrossOrigin注释后仍然出现CORS错误