带 Cors 的跨域请求

Posted

技术标签:

【中文标题】带 Cors 的跨域请求【英文标题】:Cross Domain Request w/ Cors 【发布时间】:2016-05-05 03:53:02 【问题描述】:

我有一个 ember 解决方案,它在 http://localhost:4200 上本地运行。它从我的使用 Windows 身份验证的 WebApi 应用程序请求数据。目前在http://localhost:11470 上运行。由于某些奇怪的原因,当我的 WebApi 应用程序响应时,它会遗漏以下内容,例如:Access-Control-Allow-Origin。从而抛出以下异常:

XMLHttpRequest 无法加载 http://localhost:11470/api/Authentication/logins。回应 预检请求未通过访问控制检查:否 请求中存在“Access-Control-Allow-Origin”标头 资源。因此不允许使用原点“http://localhost:4200” 使用权。响应的 HTTP 状态代码为 401。

如果我查看请求,我清楚地看到 WebApi 应用程序未在标头中包含此类数据。我该如何纠正我的问题?

// Inside: 'WebApiConfig'
configuration.EnableCors(new EnableCorsAttribute("http://localhost:4200", "*", "*")  SupportsCredentials = true );

// Controller:
[Route("api/Authentication/Logins")]
public IHttpActionResult Login()

     if (User.Identity.IsAuthenticated)
          return Ok();      

     return Unauthorized();


// Ember Ajax:
Ember.$.ajax(
     type: "GET",
     url: 'http://localhost:11470/api/Authentication/logins',
     crossDomain: true,
     headers:
          'Authorization': 'WWW-authenticate'
     ,
     xhrFields: 
          withCredentials: true
     ,
     error: function()  console.log('Error'); ,
     success: function()  console.log('Working?'); 
);

我什至尝试了以下方法:

强制web.config中的标头信息。 IHttpActionResult的自定义实现 ActionFilterAttribute 的自定义过滤器实现。

那些在控制台错误之前没有命中。为 WebApi 应用程序启用的所有功能都是 Windows 身份验证,如果我直接导​​航到 localhost:11470/api/authentication/login,它会提示我输入我的 Active Directory 凭据,然后正确响应。

我已经阅读了几篇文档,例如:

http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api https://msdn.microsoft.com/en-us/magazine/dn532203.aspx?f=255&MSPPError=-2147217396 http://www.html5rocks.com/en/tutorials/cors/

我无法找到可靠工作的解决方案,我缺少什么或不理解什么?我知道它需要标头,但是为什么 WebApi 的 Cors 库没有发送它?

【问题讨论】:

为什么不在开发中使用 ember-cli 中的 --proxy,因为在生产中您希望将 ember 应用程序托管在与 asp.NET 应用程序相同的 IIS 中? 这仍然会导致同样的错误,是的,你是对的,我可以在同一个 IIS 应用程序池和实例中同时运行。但我想了解我遇到这种情况的原因。 您能否在进行 AJAX 调用时提供有关请求/响应标头的更多信息,可能正在使用 fiddler 之类的工具 基本上你的请求头应该有 Origin: localhost:4200 并且响应头应该有 Access-Control-Allow-Origin: localhost:4200 或 * @CleanCrispCode 是的,我可以,我知道我需要 Access-Control-Allow-Origin,但由于某些奇怪的原因,我的 WebApi 没有将其发回。 【参考方案1】:

添加包

<?xml version="1.0" encoding="utf-8"?>
 <packages>
   <package id="Microsoft.AspNet.Cors" version="5.2.3" targetFramework="net461" />
   <package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net461" />
   <package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net461" />
   <package id="Microsoft.AspNet.WebApi.Cors" version="5.2.3" targetFramework="net461" />
   <package id="Newtonsoft.Json" version="6.0.4" targetFramework="net461" />
 </packages>


public static void Register(HttpConfiguration config)
         
             config.MapHttpAttributeRoutes();

             //config.EnableCors();
             var cors = new EnableCorsAttribute("*", "*", "*");

             config.EnableCors(cors);
             config.Routes.MapHttpRoute(
                 name: "DefaultApi",
                 routeTemplate: "api/controller/id",

jQuery

url: ApiPath + "/api/Orders/OrderNumber/" + orderNo,
         dataType: "json",
         crossDomain: true,
         headers:  "__RequestVerificationToken": AntiForgery.getToken() ,
         //headers:  "__RequestVerificationToken": AntiForgery.getToken() ,
         success: function (data) 
             $.each(data.ItemList, function (key, value) 
                 SettingArrayLists(value);

【讨论】:

【参考方案2】:

我在使用 Microsoft.AspNet.WebApi.Cors 包时遇到了完全相同的问题。

尝试检查 Web API 的一些事情(您提到的一些您尝试过,但我将它们与我尝试过的详细信息一起列出,以防细节存在差异):

    如果您的 API 我们使用登录信息,您需要允许 CORS 通过 SupportsCendentials 属性发送“身份验证”标头,应该通过以下方式启用:

    config.EnableCors(new EnableCorsAttribute("http://localhost:4200", "", "") SupportsCredentials = true );

但是这个解决方案实际上并没有为我工作,它没有在我的 /token OPTIONS 飞行前设置 CORS 标头,但它可能与库或 WebAPI 版本存在版本差异。

    在您的 Web.config 中检查您是否正在禁用 OPTIONS 处理程序(我认为这是默认行为),这是飞行前尝试调用的:

在 system.webServer.handlers 下:

<!--<remove name="OPTIONSVerbHandler" />--> <!--Allow options handling (preflight requests) by removing this line-->
    强制它:在 system.webServer.httpProtocol 下为您的自定义标头添加所有这些以强制它们通过(如果您尝试这样做,请禁用其他 CORS 选项)。
<customHeaders>
    <!--Enable CORS for all requests (TODO Fix this, move to OWIN settings) -->
    <add name="Access-Control-Allow-Origin" value="*" />
    <add name="Access-Control-Allow-Headers" value="Origin, Content-Type, Authorization" />
    <add name="Access-Control-Allow-Methods" value="GET, POST, OPTIONS, PUT, DELETE" />
  </customHeaders>

这些更改允许我的 API 以正确的标头响应,我建议从那里开始。

    而不是使用 Microsoft.AspNet.WebApi.Cors CORS 包并将其设置在 WebApiConfig.cs 中,您可以直接在 Startup.cs 或 Startup.Auth.cs 中的 OWIN 中间位置上设置它,并且作为 FIRST 行中的任何一个,在任何其他 OWIN pineline 之前,添加:

    app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);

【讨论】:

以上是关于带 Cors 的跨域请求的主要内容,如果未能解决你的问题,请参考以下文章

Ajax请求的跨域(CORS)问题

使用 Angular 和 NodeJs (CORS) 的跨域请求

带有 PHP 标头的跨域请求标头 (CORS)

使用 CORS 的 OPTIONS 请求宁静的跨域

带有 CORS 的跨域 POST 请求返回 access-control-allow-origin 丢失

AngularJS 中的跨域 HTTP 请求失败