IIS 中托管的 WebAPI 中的 CORS 问题

Posted

技术标签:

【中文标题】IIS 中托管的 WebAPI 中的 CORS 问题【英文标题】:CORS problems in WebAPI hosted in IIS 【发布时间】:2016-08-12 18:17:32 【问题描述】:

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

在我的应用程序中,我一直遇到 Cors 问题。在某些配置中,我会在 POST 的预检 (OPTIONS) 请求中收到 500 错误以获取令牌,或者我可以获取令牌,但随后在对实际 API 调用的 GET 请求的预检请求中收到 404 错误不记名令牌。

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

凭直觉,我尝试在本地 IIS 下托管他的 API,但发现了完全相同的问题。 (令牌的预检请求出现 500 错误,看起来实际的 API 可以正常工作)

从我一直在阅读的内容来看,这似乎是 IIS 中的模块和处理程序与 WebApi 中的 Cors 实现之间存在一些冲突,但 Taiseer 的实现在托管在 Azure 中时有效,因此这可能是 IIS 版本的差异(我目前在 Windows 7 下运行)。

我怎样才能找出导致问题的原因?

【问题讨论】:

您必须更具体地了解您遇到的错误。调查导致 500 服务器错误的异常(如果需要,请尝试远程调试),或者如果没有发现日志中的 IIS 内部错误是什么。我们目前没有足够的信息来帮助您。 【参考方案1】:

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

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

【讨论】:

【参考方案2】:

我遇到了同样的问题,我按照 Tom Hall 先生的建议做了所有事情。但是 chrome 仍然报告没有 Access-control-allow-origin 标头存在.. 在与 fidler 检查后我意识到我的请求通过代理服务器并且我的代理服务器正在处理预检选项请求..

所以在“互联网选项”中,我删除了代理服务器,发现一切正常工作...!!!

【讨论】:

【参考方案3】:

问题的根源

Token 操作不托管在控制器中,而是内置在较低级别的管道中的某个位置。对该机制的唯一访问是通过扩展OAuthAuthorizationServerProvider 的类中的覆盖方法GrantResourceOwnerCredentials()。 (在我们的例子中是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相关的有用链接

Really good description of PreFlight for CORS Excellent Sample Application using Token Auth

【讨论】:

您应该接受您的回答以结束问题。与此同时,微软后来为此发布了 IIS CORS 模块,docs.microsoft.com/en-us/iis/extensions/cors-module/…

以上是关于IIS 中托管的 WebAPI 中的 CORS 问题的主要内容,如果未能解决你的问题,请参考以下文章

IIS 托管实体框架 CORS 的 Angular 客户端不允许响应

仅在 IIS 中发布时,在 ASP.net Core 3.1 WebAPI 中启用 CORS 时出错

Angular $resource 和自托管 WebAPI 的 CORS 问题

async nlog 如何与 IIS 中托管的 webapi 一起工作?

具有自托管或 IIS 选项的 WebAPI

服务器中的 C# webapi Cors Option 请求返回错误 404 未找到