Angular2 到 REST WebApi CORS 问题

Posted

技术标签:

【中文标题】Angular2 到 REST WebApi CORS 问题【英文标题】:Angular2 to REST WebApi CORS issue 【发布时间】:2016-05-14 03:26:18 【问题描述】:

我正在使用 angular2 前端和 WebApi 后端。 webapi 启用了 CORS

var cors = new EnableCorsAttribute("*", "*", "*");
GlobalConfiguration.Configuration.EnableCors(cors);

它可以工作,因为我有不同的网站(jQuery/javascript)使用这个 api。但是对于 angular2 它没有。我收到以下消息:

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

也许与“预检请求”有关?

【问题讨论】:

我阅读了“在 ASP.NET Web API 中启用跨域请求”的文档,您应该在响应中包含此标头。请参阅本页中的“CORS 工作原理”部分:asp.net/web-api/overview/security/…。 我要关闭它,因为它只是每个 OP 的拼写错误。 我认为服务器属性中的这个问题参见:***.com/questions/36825429/… 【参考方案1】:

请按照 WEB API 中的 CROS ISSUE 修复步骤进行操作:

    在应用程序中启用 CORS 所需的标头。即在“Global.asax”文件中的“Application_BeginRequest”方法中用于简单请求。

    将以下代码放在“web.config”文件中有助于解决预检请求的 CORS 问题

    <system.webServer>
              <handlers>
                <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
                <remove name="OPTIONSVerbHandler" />
                <add name="ExtensionlessUrlHandler-Integrated-4.0"path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
              </handlers>
            </system.webServer>
    

参考: https://docs.microsoft.com/en-us/aspnet/web-api/overview/security/enabling-cross-origin-requests-in-web-api#enable-cors

【讨论】:

【参考方案2】:

在我的例子中,我使用了 Owin,并且不得不将以下行移动到启动的开头

public class Startup
    
        public void Configuration(IAppBuilder app)
        
            app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);

            ...
        
    

【讨论】:

【参考方案3】:

我也很难使用 cors 和 angular 6。

当对服务器的请求不是基本请求时,会有预检请求询问您的服务器是否可以响应您的请求。

响应该请求的服务器应具有这些标头:

Access-Control-Allow-Origin // 应该是您的域

Access-Control-Allow-Headers // 应该是 Accept、Origin 以及您可能拥有的任何其他标头。

Access-Control-Allow-Method // 你使用的任何方法

这些是您添加为 Cors 属性的“*”、“*”、“*”以接受所有 但这仅在客户端和服务器都在同一台机器上时在开发模式下对我有用。 在我使用 IIS 服务器转移到生产环境后,这些值不再起作用,尤其是由于标题。

所以它真的很容易修复,它也适用于 ios 相反 * * * 我将这个添加到每个控制器:

[EnableCors(origins: "enter your domain here", headers: "authorization, Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers", methods: "GET,POST", PreflightMaxAge = 600 // optional, SupportsCredentials = true // optional)]

您可以在帮助我了解我需要做什么的文章中阅读更多内容: https://msdn.microsoft.com/en-us/magazine/dn532203.aspx

希望对你有帮助, 汤姆。

【讨论】:

【参考方案4】:

为开发目的添加this Chrome 扩展并启用跨域资源共享。

【讨论】:

即使扩展程序正常工作,这也是一个糟糕的解决方案。 OP 需要正确设置 CORS 标头在他的服务器上 @sr9yar 是的,这不是一个永久的解决方案,但如果你有一些服务器依赖项,那么你可以继续使用这个 chrome 扩展。【参考方案5】:

您可以在 Firefox 浏览器中添加一个插件。它将像魅力一样在您的 Firefox 浏览器中运行。 Cors Everywhere 解决了我的问题。 https://addons.mozilla.org/en-US/firefox/addon/cors-everywhere/

【讨论】:

【参考方案6】:

我正在使用 Angular 2 作为前端和 nodeJS (Expressjs) 到 API

Angular 2 在 localhost:3000 下工作,而 express 在 localhost:8000 下工作

当 localhost:3000 尝试使用 POST 方法调用 URL 时会出现问题... expressJS 服务器拒绝调用,因为它来自另一个服务器(或端口)

要解决这个问题,你应该告诉 node js 接受来自 localhost:3000 服务器的调用...

You can find a library (CORS) to avoid this problem in this link:

【讨论】:

【参考方案7】:

我知道问题不是要求 php 代码。我来到这里是因为整个预检和 Angular2。当我查看 Matteo 的答案时,我意识到为什么对我的服务器的请求返回 401。这是因为在预检中浏览器不发送授权令牌,因此服务器返回 401 并且浏览器认为不允许使用 CORS .请注意,除非您知道自己在做什么,否则下面的代码只能在开发服务器中使用。

在 PHP 中你可以这样做:

if (strtolower($_SERVER['REQUEST_METHOD']) === 'options') 
         header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']);
         header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
         header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Range, Content-Disposition, Content-Type, Authorization');
         header('Access-Control-Allow-Credentials: true');
         echo 'Allowed';
         exit;

nginx

if ($request_method = 'OPTIONS') 
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        #
        # Custom headers and headers various browsers *should* be OK with but aren't
        #
        add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
        #
        # Tell client that this pre-flight info is valid for 20 days
        #
        add_header 'Access-Control-Max-Age' 1728000;
        add_header 'Content-Type' 'text/plain charset=UTF-8';
        add_header 'Content-Length' 0;
        return 204;
     

记住您发送到服务器的任何其他标头都必须添加到 Access-Control-Allow-Headers 列表中。

【讨论】:

【参考方案8】:

我在 Angular2 应用程序中遇到了同样的问题。 如前所述,问题是在客户端发出的每个请求之前,预检请求都会发送到服务器。

这种类型的请求具有 OPTIONS 类型,服务器有责任发回 preflight 响应,状态为 200 并设置用于接受来自该客户端的请求的标头.

这是我的解决方案(带快递):

// Domain you wish to allow
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');

// Request methods you wish to allow
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');

// Request headers you wish to allow
res.setHeader('Access-Control-Allow-Headers', 'YOUR-CUSTOM-HEADERS-HERE');

// Set to true if you need the website to include cookies in  requests
res.setHeader('Access-Control-Allow-Credentials', true);

// Check if preflight request
if (req.method === 'OPTIONS') 
    res.status(200);
    res.end();

else 
    // Pass to next layer of middleware
    next();

如您所见,如果请求类型是 OPTIONS,我设置了标头然后获取。在这种情况下,我发回状态 200 并结束响应。

通过这种方式,客户端将获得授权,您还可以在所有请求中设置自定义标头。

【讨论】:

你把这些行放在哪里了? 在路由声明之前。 成功了,谢谢。我使用了the CORS middleware,但它没有用。为什么?这段代码不是在做同样的事情吗? 非常感谢!这个解决方案也适用于 PHP-Angular【参考方案9】:

您的 web.config 文件中是否为 cors 设置了任何选项?即类似&lt;add name="Access-Control-Allow-Origin" value="*"/&gt;

如果是,请确保将其删除,并仅通过代码控制 cors。

答案here 会帮助你。

【讨论】:

【参考方案10】:

您的错误消息表明您的呼叫响应中没有Access-Control-Allow-Origin。为此请求启用 CORS 是必要的。这与 Angular2 无关。

这是通过在请求中添加Origin 标头在客户端触发的。您的请求中有此标头吗?您是否在其他应用程序中使用预检请求。提醒一下:

简单的请求。如果我们使用 HTTP GET、HEAD 和 POST 方法,则此用例适用。对于 POST 方法,仅支持具有以下值的内容类型:text/plainapplication/x-www-form-urlencodedmultipart/form-data预检请求。当“简单请求”用例不适用时,会发出第一个请求(使用 HTTP OPTIONS 方法)以检查在跨域请求的上下文中可以做什么。

也许 OPTIONS 请求未在服务器端正确处理(不返回正确的标头,...)。

感兴趣的是告诉我们错误发生在哪些请求上:OPTIONS 之一或目标请求。您可以查看 DevTools 中的 Network 选项卡...

有关 CORS 工作原理的更多详细信息,请参阅以下链接:

http://restlet.com/blog/2015/12/15/understanding-and-using-cors/ http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api#enable-cors

希望对你有帮助, 蒂埃里

【讨论】:

+1 当我在客户端上苦苦挣扎时,给了我正确的方向,但飞行前错误是因为服务器阻塞了带有一些标头的 cors 请求。所以必须允许我的场景中的所有标题。 @Thierry Templier 你能看看这个question吗? 很好的解释。 @"Matteo Tosi" 给出了解决方案

以上是关于Angular2 到 REST WebApi CORS 问题的主要内容,如果未能解决你的问题,请参考以下文章

Angular 2登录到Django Rest Framework后端

使用 Angular2 将 MultipartFile 作为请求参数发送到 REST 服务器

为啥在路由到 REST WebAPI 获取方法时需要内容类型标头?

在 Angular2/4/5 中,如何基于基于令牌的身份验证安全地调用 WebAPI 操作

Angular2 使用一个 REST 调用的多个组件

带有angular2的spring mvc(rest)导致302暂时移动