IIS中托管的WebAPI中的CORS问题

时间:2016-04-20 08:05:57

标签: iis asp.net-web-api cors preflight

我尝试使用Taiseer Joudeh在此really awesome example中演示的相同的基于令牌的身份验证机制来实现一个应用程序。

在我的应用程序中,我一直遇到Cors问题。在某些配置中,我会在POST的Preflight(OPTIONS)请求中获得500错误以获取令牌,或者我可以获得令牌但是在预检请求上获得404错误,以获得对实际API调用的GET请求持票人令牌。

一个区别是Taiseer的代码设置为在IISExpress(或Azure)中托管,而我的托管在本地IIS上(目前在Windows 7上运行)。

在预感中,我尝试在本地IIS下托管他的API,我发现了完全相同的问题。 (对于令牌的预检请求有500个错误,看起来实际的API将正常工作)

从我读过的内容来看,似乎这可能是IIS中的模块和处理程序与WebApi中的Cors实现之间存在冲突,但是当在Azure中托管时,Taiseer的实现可能会工作,所以它可能是一个IIS版本的差异(我目前在Windows 7下运行)。

如何理清造成问题的原因?

3 个答案:

答案 0 :(得分:1)

它不是您正在使用的IdentityServer,但它可能是同一个问题。关于IdentityServer的Github page,您必须在IIS下运行时为您的应用程序激活RAMMFAR(runAllManagedModulesForAllRequests)。

<system.webServer>
  <modules runAllManagedModulesForAllRequests="true">
  </modules>
</system.webServer>

答案 1 :(得分:1)

问题的根源

令牌操作不是托管在控制器中,而是建在较低级别管道中的某个位置。对机制的唯一访问是通过扩展GrantResourceOwnerCredentials()的类中的覆盖方法OAuthAuthorizationServerProvider。 (在我们的例子中是ApplicationOAuthProvider.cs)。

GrantResourceOwnerCredentials()确实有上下文可用,但它不是作为PreFlight请求的一部分调用的,因此您无法为CORS插入相应的PreFlight响应头。

解决方案

我们最终确定了以下解决方案。我不是它的忠实粉丝,因为它会强制这些标题进入每个响应,但至少它是有效的。

解决方案是覆盖Global.asax中的Application_PreSendRequestHeaders()方法以插入适当的标头。

的Global.asax.cs

    void Application_PreSendRequestHeaders(Object sender, EventArgs e)
    {
        var origin = Request.Headers.Get("Origin");
        var validOrigins = ConfigurationManager.AppSettings["allowedCorsOrigins"].Split(',');
        if(validOrigins.Any(o => o == origin))
        {
            Response.Headers.Set("Access-Control-Allow-Origin", origin);
            Response.Headers.Set("Access-Control-Allow-Credentials", "true");
            Response.Headers.Set("Access-Control-Allow-Headers", "Content-Type, Accept, Authorization, withcredentials, Prefer");
            Response.Headers.Set("Access-Control-Expose-Headers", "Claims, *");
            Response.Headers.Set("Access-Control-Max-Age", "600");
            Response.Headers.Set("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE,OPTIONS");
        }
    }

这需要以下web.config条目:

的web.config

<configuration>
  <appSettings>
    <add key="allowedCorsOrigins" value="http://www.allowedsite1.net,http://localhost:22687" />
    <add key="allowedCorsMethods" value="get, post, put, delete, options, batch" />
    <add key="allowedCorsHeaders" value="*" />
  </appSettings>
...
</configuration>

循环搜索有效来源的原因是您无法回复允许的来源列表......

这解决了大多数问题,但有一个例外(如果我没记错的话是PUT和DELETE动词的问题)。这需要删除“ExtensionlessUrlHandler-Integrated-4.0”并在web.config的处理程序部分中使用路径和动词重新添加它。

web.config(第二次更改)

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

与CORS相关的有用链接

答案 2 :(得分:1)

我有同样的问题,我按照汤姆先生的建议做了很多事。但仍然镀铬报告没有存在Access-control-allow-origin标头..在用fidler检查后我意识到我的请求通过代理服务器并且我的代理服务器正在处理预检选项请求..

所以&#34;互联网选项&#34;我删除了代理服务器,发现一切都正常工作 ...... !!!