多个 CORS 标头“Access-Control-Allow-Origin”不允许/CORS 标头“Access-Control-Allow-Origin”缺失)

Posted

技术标签:

【中文标题】多个 CORS 标头“Access-Control-Allow-Origin”不允许/CORS 标头“Access-Control-Allow-Origin”缺失)【英文标题】:Multiple CORS header ‘Access-Control-Allow-Origin’ not allowed / CORS header ‘Access-Control-Allow-Origin’ missing) 【发布时间】:2019-06-19 22:28:28 【问题描述】:

当我从 Angular 7 应用程序(托管在 http://localhost:4200)从 Firefox 向我的 Spring-Boot 应用程序(托管在 https://localhost:8924)发送 HTTP 请求时,我遇到了 CORS 标头问题。

我的 Spring-Boot 应用程序中有一个 CORS 过滤器,该过滤器已添加到我的请求中:

@Component
public class CorsFilter extends OncePerRequestFilter 

    @Override
    protected void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response,
                                    final FilterChain filterChain) throws ServletException, IOException 
        response.addHeader("Access-Control-Allow-Origin", "*");
        response.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, PATCH, HEAD");
        response.setHeader("Access-Control-Allow-Headers", "X-Requested-With, Authorization, Content-Type");
        response.addIntHeader("Access-Control-Max-Age", 3600);

        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) 
        
            response.setStatus(HttpServletResponse.SC_OK);
         
        else 
        
            filterChain.doFilter(request, response);
        
    

    @Override
    protected void configure(HttpSecurity http) throws Exception 
    
        http.addFilterBefore(corsFilter(), SessionManagementFilter.class);
        http.csrf().disable().
            authorizeRequests()
                .antMatchers("/api/auth/**","/api/MentorCalendar","/api/user/role/**").permitAll()
                .anyRequest().authenticated()
                .and()
                .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
    

发送请求时,Firefox 控制台返回此错误消息:

跨域请求被阻止:同源策略不允许读取位于http://localhost:8924/api/auth/signin 的远程资源。 (原因:不允许使用多个 CORS 标头“Access-Control-Allow-Origin”)。

注释掉 Access-Control-Allow-Origin:

@Component
public class CorsFilter extends OncePerRequestFilter 

    @Override
    protected void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response,
                                    final FilterChain filterChain) throws ServletException, IOException 
//        response.addHeader("Access-Control-Allow-Origin", "*");
        response.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, PATCH, HEAD");
        response.setHeader("Access-Control-Allow-Headers", "X-Requested-With, Authorization, Content-Type");
        response.addIntHeader("Access-Control-Max-Age", 3600);

        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) 
        
            response.setStatus(HttpServletResponse.SC_OK);
         
        else 
        
            filterChain.doFilter(request, response);
        
    

返回此错误消息:

跨域请求被阻止:同源策略不允许读取位于http://localhost:8924/api/auth/signin 的远程资源。 (原因:缺少 CORS 标头“Access-Control-Allow-Origin”)。

src/app/home/login.component.ts 提取

export class LoginComponent 
  constructor(private LoginService: LoginService, private router: Router) 

  login(inputUsername, inputPassword)
    this.LoginService.login(username: inputUsername, password: inputPassword)
        .subscribe(data => 
        localStorage.setItem("jwtToken", data.accessToken);

src/app/home/login.service.ts

const httpOptions = 
  headers: new HttpHeaders(
    'Content-Type':  'application/json'
  )
;

@Injectable()
export class LoginService 
  loginUrl = "http://localhost:8924/api/auth/signin";

  constructor( private http: HttpClient ) 

  login(loginCreds: any): Observable<any> 
  return this.http.post<any>(this.loginUrl, loginCreds, httpOptions);
  

response.addHeader("Access-Control-Allow-Origin", "*");包含时设置多个标题但删除时没有设置?

【问题讨论】:

【参考方案1】:

您是否尝试在您的 springboot 控制器中启用 @CrossOrigin()。下面是基本的sn-p。

@CrossOrigin(origins = "http://localhost:9000")
@GetMapping("/greeting")
public Greeting greeting(@RequestParam(required=false, defaultValue="World") String name) 
    System.out.println("==== in greeting ====");
    return new Greeting(counter.incrementAndGet(), String.format(template, name));

欲了解更多信息,请访问Enabling CORS

我遇到了同样的问题。通过上面的解决方案解决了。使用 Internet Explorer 时一定不是 CORS 问题。

【讨论】:

我所有的控制器都有 CrossOrigin 符号。在我开始在同一个控制器中进行两次 HTTP 调用之前,我最初对 CORS 没有任何问题,其中第二次调用返回了预检错误,因此我开始自己设置标头。【参考方案2】:

这已经为我解决了这个问题:

if(!response.containsHeader("Access-Control-Allow-Origin"))

    response.addHeader("Access-Control-Allow-Origin", "*"); 

不是让它工作的理想方式

【讨论】:

【参考方案3】:

在我的情况下,当我在 nginx conf 文件和 Django 中间件中同时设置 CORS 支持时,就会发生这种情况。

Nginx 部分:

if ($request_method = 'OPTIONS') 
    add_header 'Access-Control-Allow-Origin' '*';
    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
    add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
    add_header 'Access-Control-Max-Age' 1728000;
    add_header 'Content-Type' 'text/plain; charset=utf-8';
    add_header 'Content-Length' 0;
    return 204;

if ($request_method = 'POST') 
    add_header 'Access-Control-Allow-Origin' '*';
    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
    add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
    add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';

if ($request_method = 'GET') 
    add_header 'Access-Control-Allow-Origin' '*';
    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
    add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
    add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
    

Django 部分:

MIDDLEWARE = (
    'corsheaders.middleware.CorsMiddleware',

解决方案非常简单——我只是删除了 nginx 中的 CORS 部分,一切正常

location / 
    uwsgi_pass  django_upstream;
    include     uwsgi_params;

【讨论】:

以上是关于多个 CORS 标头“Access-Control-Allow-Origin”不允许/CORS 标头“Access-Control-Allow-Origin”缺失)的主要内容,如果未能解决你的问题,请参考以下文章

即使存在标头,CORS 也会失败

即使存在标头,CORS 也会失败

在 IE10 的 AJAX CORS 请求中添加自定义标头时,CORS 请求中止

IE XdomainRequest CORS 问题

离子4中的Cors问题

CORS 多个标头