Angular2-响应预检请求未通过访问控制检查:所请求的资源上不存在“Access-Control-Allow-Origin”头部

8

我正在Angular 2中调用一个HTTP post请求。在Postman中这个请求可以正常工作,但是当我将这个API调用添加到Angular 2中时,会收到“没有'Access-Control-Allow'”错误。以下是我的代码:

getInspections(): Observable<IInspection[]> {
        if (!this.inspections) {
            let body =JSON.stringify({"Statuses":["Submitted", "Opened"]});
            let headers = new Headers({ 'Content-Type': 'application/json' });

            headers.append('Access-Control-Allow-Origin','*');
            let options = new RequestOptions({ headers: headers });

            return this.http.post(this._baseUrl + '/api/Inspect/ListI',body,options)
                .map((res: Response) => {
                    this.inspections = res.json();
                    return this.inspections;
                })
                .catch(this.handleError);
        }
        else {
            //return cached data
            return this.createObservable(this.inspections);
        }
    }

或者我可以这样做吗?只需传递标头而不是选项。
getInspections(): Observable<IInspection[]> {
        if (!this.inspections) {
            let body =JSON.stringify({"Statuses":["Submitted", "Opened"]});
            let headers = new Headers({ 'Content-Type': 'application/json' });

            //headers.append('Access-Control-Allow-Origin','*');
          //  let options = new RequestOptions({ headers:headers });

            return this.http.post(this._baseUrl + '/api/Inspect/ListI',body,headers)
                .map((res: Response) => {
                    this.inspections = res.json();
                    return this.inspections;
                })
                .catch(this.handleError);
        }
        else {
            //return cached data
            return this.createObservable(this.inspections);
        }
    }

你可以直接传递header(我猜应该是一个对象,类似于 {headers} (不确定)但这与你的CORS错误无关。 - Günter Zöchbauer
2个回答

11

CORS头信息如下:

headers.append('Access-Control-Allow-Origin','*');

这些信息需要由服务器提供。在客户端添加它们是没有意义的。


我正在使用第三方API,那么我该如何在那里添加标头? - sainanky
这可能意味着所有者不希望您以这种方式使用API。您可以通过通过您控制的服务器中继请求来解决此问题。CORS仅适用于从浏览器发出的请求,而不适用于从服务器发出的请求。 - Günter Zöchbauer

3
当使用非标头(JSON 显然被认为是非标头)时,会进行预检查以询问是否可以执行所请求的操作(在此情况下为“post”)。只有服务器才能用宽松标头响应。如何响应取决于您的服务器语言。在我的 WebAPI2 中,我在 WebAppConfig 中实现 CORS。
 var cors = new EnableCorsAttribute("http://localhost:3000", "*", "GET, HEAD, OPTIONS, POST, PUT");
        cors.SupportsCredentials = true;
        config.EnableCors(cors);

请注意,在实际服务器上,您需要将本地主机引用替换为Web配置列表(或调用方所在的特定位置)。如果您正在使用身份验证,则仅需要SupportsCredentials。

为了处理预检请求,我在Globals.asax中添加了一个方法,该方法只是拦截预检消息并返回足够的数据以便后续请求可以继续进行。

protected void Application_BeginRequest()
    {
        if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
        {
            var origin = HttpContext.Current.Request.Headers["Origin"];

            Response.Headers.Add("Access-Control-Allow-Origin", origin);
            Response.Headers.Add("Access-Control-Allow-Headers", "content-type, withcredentials, Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");
            Response.Headers.Add("Access-Control-Allow-Credentials", "true");
            Response.Headers.Add("Access-Control-Allow-Methods", "GET, HEAD, OPTIONS, POST, PUT");

            Response.Flush();
        }
    }

请注意,我在反射原点时有些作弊——这在生产环境中是不安全的,应该列出具体的服务器,否则你对安全性过于宽松。
请注意,有一些开发人员可以使用的小技巧。如果您在本地主机上使用 Internet Explorer(用于开发目的),IE会忽略大多数其他浏览器没有忽略的端口,因此可以使事情变得更加容易。还有一个针对 Chrome 的CORS增强功能,可以为您添加标头。最后,您将看到很多代码使用“*”返回(允许所有内容)——可以使用它们来使代码工作,但在发布之前要更严格地锁定这些代码。

当你说“只有服务器可以响应宽松的标头”时,我并不是很理解你的意思。后来又提到:“Chrome还有一个CORS增强功能,可以为您添加标头。” 但Chrome不是在客户端吗? - fralbo
建议您调查一下Chrome的CORS增强功能,这可以解决您的困惑。该增强功能可以在开发环境中解决一些有限的问题。但是生产环境需要全面的答案。 - Matrim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接