Cors的跨域请求

时间:2016-01-27 23:30:55

标签: c# ember.js asp.net-web-api cors cross-domain

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

  

XMLHttpRequest无法加载   http://localhost:11470/api/Authentication/logins。回应   预检请求未通过访问控制检查:否   '访问控制允许来源'标题出现在请求的上   资源。起源' 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凭据,然后正确响应。

我已阅读了多份文件,例如:

我无法获得可靠工作的解决方案,我缺少什么或不理解?我知道它需要标题,但为什么WebApi的Cors库不发送它?

2 个答案:

答案 0 :(得分:1)

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

尝试检查Web API的一些事情(你提到过的一些尝试,但是我列出了我尝试过的详细信息,但是具体情况有所不同):

  1. 如果您的API使用登录信息,您需要允许CORS发送"身份验证"通过SupportsCendentials属性的标头,启用以下内容:

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

  2. 但是这个解决方案实际上并不适用于我,它没有在我的/ token OPTIONS运行前设置CORS标头,但它可能是与库或WebAPI版本的版本差异。 / p>

    1. 在您的Web.config中检查您是否禁用了OPTIONS处理程序(我认为这是默认行为),这是飞行前试图调用的内容:
    2. 在system.webServer.handlers下:

      <!--<remove name="OPTIONSVerbHandler" />--> <!--Allow options handling (preflight requests) by removing this line-->
      
      1. 强制它:在system.webServer.httpProtocol下,为您的自定义标头添加所有这些以强制它们通过(如果您尝试这样做,则禁用其他CORS选项)。
      2. <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使用正确的标头进行响应,我建议从那里开始。

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

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

答案 1 :(得分: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);
}}}}