我正在尝试在我的WebAPI项目中启用CORS支持,如果启用了匿名身份验证,那么一切正常,但是使用Windows Auth +禁用的匿名身份验证,发送的OPTIONS请求始终返回401未经授权的响应。要求它的网站位于DOMAIN上,因此应该可以拨打电话,在不禁用Windows身份验证的情况下有什么方法可以解决此问题?
匿名用户只能使用OPTIONS动词。
<system.web>
<authentication mode="Windows" />
<authorization>
<allow verbs="OPTIONS" users="*"/>
<deny users="?" />
</authorization>
</system.web>
根据W3C规范,浏览器从CORS预检中排除了用户凭据:https://dvcs.w3.org/hg/cors/raw-file/tip/Overview.html#preflight-request
扩展了@dariusriggins提供的答案。检查此帖子:Microsoft | Developer: Putting it all together – CORS tutorial
对于IIS配置:
授权规则
授权阶段(或授权事件),我们需要确保仅允许来自CORS预检的匿名请求,并要求所有其他传入请求都提供身份验证凭据。我们可以通过授权规则来实现。默认情况下,授予所有用户访问该站点的权限的授权规则已经存在,并且由IIS默认提供。我们将从修改此规则开始,以仅允许匿名用户发送使用OPTIONS http动词的请求。以下是此授权规则在IIS中的目标配置:
编辑授权规则
对我有用的(使用AngularJS或JQuery时,是将withCredentials:true添加到客户端上的每个请求:
$http.get("http://localhost:88/api/tests", {withCredentials :true})
并在服务器上启用CORS,这是通过nuget的Microsoft.Owin.Cors完成的,并将其添加到Startup中,如下所示:
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
ConfigureOAuth(app);
WebApiConfig.Register(config);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app.UseWebApi(config);
}
参考:
在WebApiConfig.cs中的EnableCorsAttribute上启用SupportCredentials为我成功了:
public static void Register(HttpConfiguration config)
{
//enable cors request just from localhost:15136
var cors = new EnableCorsAttribute("http://localhost:15136", "*", "*");
cors.SupportsCredentials = true;
config.EnableCors(cors);
//other stuff
}
https://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api
确保从javascript调用时发送凭据({withCredentials :true}
)
数年后,但是通过@dariusriggins和@ lex-li的回答,我设法将以下代码添加到我的Global.asax中:
public void Application_BeginRequest(object sender, EventArgs e)
{
string httpOrigin = Request.Params["HTTP_ORIGIN"];
if (httpOrigin == null) httpOrigin = "*";
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", httpOrigin);
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, X-Token");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials", "true");
if (Request.HttpMethod == "OPTIONS")
{
HttpContext.Current.Response.StatusCode = 200;
var httpApplication = sender as HttpApplication;
httpApplication.CompleteRequest();
}
}
httpOrigin实际上是在允许的主机列表中查找的,但这只是复杂的事情。这意味着所有其他请求都经过验证,但选项仅返回。
感谢这个问题,没有它我会迷路的!
从MS:
[如果您禁用匿名身份验证,则设计使IIS将对任何请求返回401。如果他们启用了Windows身份验证,则在这种情况下,401响应将具有WWW-Authenticate标头,以允许客户端启动身份验证握手。然后,问题就变成了客户所使用的客户端是否可以进行Windows身份验证。
最后,似乎可能存在一个潜在的问题,即是否可以配置URL以使一个动词(在这种情况下为OPTIONS)允许匿名访问,但对其他动词要求Windows身份验证。 IIS不通过简单的配置支持此功能。通过启用匿名身份验证和Windows身份验证,在拒绝访问匿名用户的内容上设置ACL,然后配置所讨论的URL的处理程序映射,使其不验证是否存在该URL,可能会出现此行为。与URL关联的文件。但是要确认这一点还需要花费一些时间。
解决此问题的最简单方法是使用条件request_method = ^ OPTIONS $创建重写规则。然后将操作设置为自定义响应,将其设置为200 OK。然后,所有选项请求将以200而不是401进行响应。这将解决CORS问题。
当然,您仍然需要确保您具有正确的跨源请求标头。
启用集成身份验证后,这将停止选项请求(不具有任何凭据)以401响应。
接受的答案是正确的,但是我使用“带有iisnode和npm cors模块的节点”设置对REST API进行了一段时间的故障排除,对于仅对所有用户启用匿名身份验证并不满意。由于它是节点应用程序,因此system.web标记的作用不大。我最终在web.config中添加了以下内容:
<system.webServer>
<security>
<requestFiltering>
<hiddenSegments>
<add segment="node_modules" />
</hiddenSegments>
</requestFiltering>
<authorization>
<add accessType="Allow" verbs="OPTIONS" users="?" />
<add accessType="Deny" verbs="GET, PUT, POST, DELETE" users="?" />
</authorization>
</security>
</system.webServer>
由于IE 10 and 11中的错误,我今天遇到了同样的问题,我使用的是ServiceStack而不是WebApi,但是这种方法也可以为您服务。
通过所有过滤器后,它将执行服务。
在我的AppHost中,
appHost.Plugins.Add(new CorsFeature());
appHost.RequestFilters.Add(AuthenticateFilter.Authenticate);
除了添加标头之外,我还修改了CorsFeature以处理OptionsRequest,验证过滤器可以检查已验证的请求!
Related Question: IIS hijacks CORS Preflight OPTIONS request
[在多个地方找到的答案中合并信息。如果您需要在Intranet上使用Windows身份验证在ASP.net页面方法上启用CORS,这似乎是可行的。如果不更改web.config
,则无法使用。
您需要将此添加到Global.asax
protected void Application_BeginRequest(object sender, EventArgs e)
{
string httpOrigin = HttpContext.Current.Request.Params["HTTP_ORIGIN"] ?? HttpContext.Current.Request.Params["ORIGIN"] ?? "*";
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", httpOrigin);
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, X-Token");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials", "true");
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
HttpContext.Current.Response.StatusCode = 200;
var httpApplication = sender as HttpApplication;
httpApplication.CompleteRequest();
}
}
这是web.config
<system.webServer>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*."
verb="*" type="System.Web.Handlers.TransferRequestHandler"
preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
我正在使用Web API和OWIN,并且尝试了所有建议的解决方案,但以下唯一有效的方法是
//use it in your startup class
app.Use((context, next) =>
{
if (context.Request.Headers.Any(k => k.Key.Contains("Origin")) && context.Request.Method == "OPTIONS")
{
context.Response.StatusCode = 200;
context.Response.Headers.Add("Access-Control-Allow-Origin", new string[1] { "ALLOWED_ORIGIN" });
context.Response.Headers.Add("Access-Control-Allow-Headers", new string[4] { "Origin", "X-Requested-With", "Content-Type", "Accept" });
context.Response.Headers.Add("Access-Control-Allow-Methods", new string[5] { "GET", "POST", "PUT", "DELETE", "OPTIONS" });
context.Response.Headers.Add("Access-Control-Allow-Credentials", new string[1] { "true" });
return context.Response.WriteAsync("");
}
return next.Invoke();
});
//this is important! Without it, it didn't work (probably because the middleware was too late)
app.UseStageMarker(PipelineStage.Authenticate);
您需要将此代码插入您的OWIN启动类之一中的某个位置。调用app.UseStageMarker(PipelineStage.Authenticate)
很重要,因为否则预检检查会失败。UseStageMarker的更多信息-> https://docs.microsoft.com/en-us/aspnet/aspnet/overview/owin-and-katana/owin-middleware-in-the-iis-integrated-pipeline
同样重要的是,您需要显式定义允许的标头。如果使用*
作为占位符,它将失败。
也许可以帮助某人。
我理解这是一个古老的问题,提供了几种可能的解决方案(以及更多问题),但是如果其他人遇到此问题,IIS CORS 1.0将从17年11月开始可用:
https://blogs.iis.net/iisteam/introducing-iis-cors-1-0
https://docs.microsoft.com/en-us/iis/extensions/cors-module/cors-module-configuration-reference
您可以通过IIS Windows平台安装程序(WPI)下载它。这样可以解决您的许多CORS身份验证问题。享受!